Compare commits
No commits in common. "main" and "v0.2" have entirely different histories.
42
CHANGELOG.md
42
CHANGELOG.md
|
@ -7,44 +7,10 @@ All notable changes to this project will be documented in this file.
|
|||
## Unreleased
|
||||
|
||||
#### Links
|
||||
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.2.1...HEAD
|
||||
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.2.1...HEAD
|
||||
- github: https://github.com/lindeas/jilo-web/compare/v0.2.1...HEAD
|
||||
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.2.1...HEAD
|
||||
|
||||
### Added
|
||||
- Added Jilo Server check and notice on error
|
||||
- Added status page
|
||||
|
||||
---
|
||||
|
||||
## 0.2.1 - 2024-10-17
|
||||
|
||||
#### Links
|
||||
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.2...v0.2.1
|
||||
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.2...v0.2.1
|
||||
- github: https://github.com/lindeas/jilo-web/compare/v0.2...v0.2.1
|
||||
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.2...v0.2.1
|
||||
|
||||
### Added
|
||||
- Added support for managing Jilo Agents
|
||||
- Authenticating to Jilo Agents with JWT tokens with a shared secret key
|
||||
- Added Jilo Agent functionality to fetch data, cache it and manage the cache
|
||||
- Added more fields and avatar image to user profile
|
||||
- Added pagination (with ellipses) for the longer listings
|
||||
- Added initial support for application logs
|
||||
- Added help page
|
||||
- Added support for graphs by Chart.js
|
||||
- Added "graphs" section in sidebar with graphs and latest data pages
|
||||
|
||||
### Changed
|
||||
- Jitsi platforms config moved from file to SQLite database
|
||||
- Left sidebar menu items reordered
|
||||
|
||||
### Fixed
|
||||
- All output HTML sanitized
|
||||
- Sanitized input forms data
|
||||
- Fixed error in calculation of monthly total conferences on front page
|
||||
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.2...HEAD
|
||||
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.2...HEAD
|
||||
- github: https://github.com/lindeas/jilo-web/compare/v0.2...HEAD
|
||||
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.2...HEAD
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ To see a demo install, go to https://work.lindeas.com/jilo-web-demo/
|
|||
|
||||
## version
|
||||
|
||||
Current version: **0.2.1** released on **2024-10-17**
|
||||
Current version: **0.2** released on **2024-08-31**
|
||||
|
||||
## license
|
||||
|
||||
|
@ -36,14 +36,11 @@ Bootstrap is used in this project and is licensed under the MIT License. See lic
|
|||
|
||||
JQuery is used in this project and is licensed under the MIT License. See license-jquery file.
|
||||
|
||||
Chart.js is used in this project and is licensed under the MIT License. See license-chartjs file.
|
||||
|
||||
## requirements
|
||||
|
||||
- web server (deb: apache | nginx)
|
||||
- php support in the web server (deb: php-fpm | libapache2-mod-php)
|
||||
- pdo and pdo_sqlite support in php (deb: php-db, php-sqlite3) uncomment in php.ini: ;extension=pdo_sqlite
|
||||
- php-curl module
|
||||
|
||||
## installation
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Jilo Web
|
||||
|
||||
## TODO
|
||||
|
||||
- ~~jilo-web.db outside web root~~
|
||||
|
||||
- ~~jilo-web.db writable by web server user~~
|
||||
|
||||
- major refactoring after v0.1
|
||||
|
||||
- - ~~add bootstrap template~~
|
||||
|
||||
- - ~~clean up the code to follow model-view--controller style~~
|
||||
|
||||
- - ~~no HTML inside PHP code~~
|
||||
|
||||
- - put all additional functions in files in a separate folder
|
||||
|
||||
- - ~~reduce try/catch usage, use it only for critical errors~~
|
||||
|
||||
- - move all SQL code in the model classes, one query per method
|
||||
|
||||
- - add 'limit' to SQL and make pagination
|
||||
|
||||
- - pretty URLs routing (no htaccess, it needs to be in PHP code so that it can be used with all servers)
|
||||
|
||||
- add mysql/mariadb option
|
|
@ -1,291 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Agent {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
// get details of a specified agent ID (or all) in a specified platform ID
|
||||
public function getAgentDetails($platform_id, $agent_id = '') {
|
||||
$sql = 'SELECT
|
||||
ja.id,
|
||||
ja.platform_id,
|
||||
ja.agent_type_id,
|
||||
ja.url,
|
||||
ja.secret_key,
|
||||
ja.check_period,
|
||||
jat.description AS agent_description,
|
||||
jat.endpoint AS agent_endpoint
|
||||
FROM
|
||||
jilo_agents ja
|
||||
JOIN
|
||||
jilo_agent_types jat ON ja.agent_type_id = jat.id
|
||||
WHERE
|
||||
platform_id = :platform_id';
|
||||
|
||||
if ($agent_id !== '') {
|
||||
$sql .= ' AND ja.id = :agent_id';
|
||||
}
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
||||
$query->bindParam(':platform_id', $platform_id);
|
||||
if ($agent_id !== '') {
|
||||
$query->bindParam(':agent_id', $agent_id);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// get details of a specified agent ID
|
||||
public function getAgentIDDetails($agent_id) {
|
||||
$sql = 'SELECT
|
||||
ja.id,
|
||||
ja.platform_id,
|
||||
ja.agent_type_id,
|
||||
ja.url,
|
||||
ja.secret_key,
|
||||
ja.check_period,
|
||||
jat.description AS agent_description,
|
||||
jat.endpoint AS agent_endpoint
|
||||
FROM
|
||||
jilo_agents ja
|
||||
JOIN
|
||||
jilo_agent_types jat ON ja.agent_type_id = jat.id
|
||||
WHERE
|
||||
ja.id = :agent_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':agent_id', $agent_id);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// get agent types
|
||||
public function getAgentTypes() {
|
||||
$sql = 'SELECT *
|
||||
FROM jilo_agent_types
|
||||
ORDER BY id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// get agent types already configured for a platform
|
||||
public function getPlatformAgentTypes($platform_id) {
|
||||
$sql = 'SELECT
|
||||
id,
|
||||
agent_type_id
|
||||
FROM
|
||||
jilo_agents
|
||||
WHERE
|
||||
platform_id = :platform_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':platform_id', $platform_id);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// add new agent
|
||||
public function addAgent($platform_id, $newAgent) {
|
||||
try {
|
||||
$sql = 'INSERT INTO jilo_agents
|
||||
(platform_id, agent_type_id, url, secret_key, check_period)
|
||||
VALUES
|
||||
(:platform_id, :agent_type_id, :url, :secret_key, :check_period)';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':platform_id' => $platform_id,
|
||||
':agent_type_id' => $newAgent['type_id'],
|
||||
':url' => $newAgent['url'],
|
||||
':secret_key' => $newAgent['secret_key'],
|
||||
':check_period' => $newAgent['check_period'],
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// edit an existing agent
|
||||
public function editAgent($platform_id, $updatedAgent) {
|
||||
try {
|
||||
$sql = 'UPDATE jilo_agents SET
|
||||
agent_type_id = :agent_type_id,
|
||||
url = :url,
|
||||
secret_key = :secret_key,
|
||||
check_period = :check_period
|
||||
WHERE
|
||||
id = :agent_id
|
||||
AND
|
||||
platform_id = :platform_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':agent_type_id' => $updatedAgent['agent_type_id'],
|
||||
':url' => $updatedAgent['url'],
|
||||
':secret_key' => $updatedAgent['secret_key'],
|
||||
':check_period' => $updatedAgent['check_period'],
|
||||
':agent_id' => $updatedAgent['id'],
|
||||
':platform_id' => $platform_id,
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// delete an agent
|
||||
public function deleteAgent($agent_id) {
|
||||
try {
|
||||
$sql = 'DELETE FROM jilo_agents
|
||||
WHERE
|
||||
id = :agent_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':agent_id', $agent_id);
|
||||
|
||||
$query->execute();
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for agent cache
|
||||
public function checkAgentCache($agent_id) {
|
||||
$agent_cache_name = 'agent' . $agent_id . '_cache';
|
||||
$agent_cache_time = 'agent' . $agent_id . '_time';
|
||||
return isset($_SESSION[$agent_cache_name]) && isset($_SESSION[$agent_cache_time]) && (time() - $_SESSION[$agent_cache_time] < 600);
|
||||
}
|
||||
|
||||
|
||||
// method for base64 URL encoding for JWT tokens
|
||||
private function base64UrlEncode($data) {
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
|
||||
// generate a JWT token for jilo agent
|
||||
public function generateAgentToken($payload, $secret_key) {
|
||||
|
||||
// header
|
||||
$header = json_encode([
|
||||
'typ' => 'JWT',
|
||||
'alg' => 'HS256'
|
||||
]);
|
||||
$base64Url_header = $this->base64UrlEncode($header);
|
||||
|
||||
// payload
|
||||
$payload = json_encode($payload);
|
||||
$base64Url_payload = $this->base64UrlEncode($payload);
|
||||
|
||||
// signature
|
||||
$signature = hash_hmac('sha256', $base64Url_header . "." . $base64Url_payload, $secret_key, true);
|
||||
$base64Url_signature = $this->base64UrlEncode($signature);
|
||||
|
||||
// build the JWT
|
||||
$jwt = $base64Url_header . "." . $base64Url_payload . "." . $base64Url_signature;
|
||||
|
||||
return $jwt;
|
||||
}
|
||||
|
||||
|
||||
// fetch result from jilo agent API
|
||||
public function fetchAgent($agent_id, $force = false) {
|
||||
|
||||
// we need agent details for URL and JWT token
|
||||
$agentDetails = $this->getAgentIDDetails($agent_id);
|
||||
|
||||
// Safe exit in case the agent is not found
|
||||
if (empty($agentDetails)) {
|
||||
return json_encode(['error' => 'Agent not found']);
|
||||
}
|
||||
|
||||
$agent = $agentDetails[0];
|
||||
$agent_cache_name = 'agent' . $agent_id . '_cache';
|
||||
$agent_cache_time = 'agent' . $agent_id . '_time';
|
||||
|
||||
// check if the cache is still valid, unless force-refresh is requested
|
||||
if (!$force && $this->checkAgentCache($agent_id)) {
|
||||
return $_SESSION[$agent_cache_name];
|
||||
}
|
||||
|
||||
// generate the JWT token
|
||||
$payload = [
|
||||
'agent_id' => $agent_id,
|
||||
'timestamp' => time()
|
||||
];
|
||||
$jwt = $this->generateAgentToken($payload, $agent['secret_key']);
|
||||
|
||||
// Make the API request
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $agent['url'] . $agent['agent_endpoint']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // timeout 10 seconds
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Authorization: Bearer ' . $jwt,
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$curl_error = curl_error($ch);
|
||||
$curl_errno = curl_errno($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
// curl error
|
||||
if ($curl_errno) {
|
||||
return json_encode(['error' => 'curl error: ' . $curl_error]);
|
||||
}
|
||||
|
||||
// response is not 200 OK
|
||||
if ($http_code !== 200) {
|
||||
return json_encode(['error' => 'HTTP error: ' . $http_code]);
|
||||
}
|
||||
|
||||
// other custom error(s)
|
||||
if (strpos($response, 'Auth header not received') !== false) {
|
||||
return json_encode(['error' => 'Auth header not received']);
|
||||
}
|
||||
|
||||
// Cache the result and the timestamp if the response is successful
|
||||
// We decode it so that it's pure JSON and not escaped
|
||||
$_SESSION[$agent_cache_name] = json_decode($response, true);
|
||||
$_SESSION[$agent_cache_time] = time();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
// clear agent cache
|
||||
public function clearAgentCache($agent_id) {
|
||||
$_SESSION["agent{$agent_id}_cache"] = '';
|
||||
$_SESSION["agent{$agent_id}_cache_time"] = '';
|
||||
}
|
||||
|
||||
|
||||
// get latest stored jilo agents data
|
||||
public function getLatestData($platform_id, $agent_type, $metric_type) {
|
||||
// retrieves data already stored in db from another function (or the jilo-server to-be)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -9,7 +9,7 @@ class Component {
|
|||
|
||||
|
||||
// list of component events
|
||||
public function jitsiComponents($jitsi_component, $component_id, $event_type, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function jitsiComponents($jitsi_component, $component_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -31,31 +31,13 @@ FROM
|
|||
WHERE
|
||||
jitsi_component = %s
|
||||
AND
|
||||
component_id = %s";
|
||||
if ($event_type != '' && $event_type != 'event_type') {
|
||||
$sql .= "
|
||||
AND
|
||||
event_type LIKE '%%%s%%'";
|
||||
}
|
||||
$sql .= "
|
||||
component_id = %s
|
||||
AND
|
||||
(time >= '%s 00:00:00' AND time <= '%s 23:59:59')
|
||||
ORDER BY
|
||||
time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
// FIXME this needs to be done with bound params instead of sprintf
|
||||
if ($event_type != '' && $event_type != 'event_type') {
|
||||
$sql = sprintf($sql, $jitsi_component, $component_id, $event_type, $from_time, $until_time);
|
||||
$sql = str_replace("LIKE '%'", "LIKE '%", $sql);
|
||||
$sql = str_replace("'%'\nAND", "%' AND", $sql);
|
||||
} else {
|
||||
$sql = sprintf($sql, $jitsi_component, $component_id, $from_time, $until_time);
|
||||
}
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
|
|
@ -9,7 +9,7 @@ class Conference {
|
|||
|
||||
|
||||
// search/list specific conference ID
|
||||
public function conferenceById($conference_id, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferenceById($conference_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -69,11 +69,6 @@ AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $conference_id, $from_time, $until_time, $conference_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -84,7 +79,7 @@ ORDER BY
|
|||
|
||||
|
||||
// search/list specific conference name
|
||||
public function conferenceByName($conference_name, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferenceByName($conference_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -144,11 +139,6 @@ AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $conference_name, $from_time, $until_time, $conference_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -159,7 +149,7 @@ ORDER BY
|
|||
|
||||
|
||||
// list of all conferences
|
||||
public function conferencesAllFormatted($from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferencesAllFormatted($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -244,11 +234,6 @@ WHERE (ce.time >= '%s 00:00:00' AND ce.time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
c.id";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -274,52 +259,25 @@ ORDER BY
|
|||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// number of conferences for time period (if given)
|
||||
// FIXME sometimes there is no start/end time, find a way around this
|
||||
// NB we need to cross check with first occurrence of "bridge selected"
|
||||
// as in Jicofo logs there is no way to get the time for conference ID creation
|
||||
$sql = "
|
||||
SELECT COUNT(*) AS conferences
|
||||
FROM (
|
||||
SELECT DISTINCT
|
||||
(SELECT COALESCE
|
||||
(
|
||||
(SELECT ce.time
|
||||
SELECT COUNT(c.conference_id) as conferences
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN (
|
||||
SELECT ce.conference_id, MIN(ce.time) as first_event_time
|
||||
FROM conference_events ce
|
||||
WHERE
|
||||
ce.conference_id = c.conference_id
|
||||
AND
|
||||
ce.conference_event = 'conference created'
|
||||
),
|
||||
(SELECT ce.time
|
||||
FROM conference_events ce
|
||||
WHERE
|
||||
ce.conference_id = c.conference_id
|
||||
AND
|
||||
ce.conference_event = 'bridge selected'
|
||||
)
|
||||
)
|
||||
) AS start,
|
||||
(SELECT COALESCE
|
||||
(
|
||||
(SELECT ce.time
|
||||
FROM conference_events ce
|
||||
WHERE
|
||||
ce.conference_id = c.conference_id
|
||||
AND
|
||||
(ce.conference_event = 'conference expired' OR ce.conference_event = 'conference stopped')
|
||||
),
|
||||
(SELECT pe.time
|
||||
FROM participant_events pe
|
||||
WHERE
|
||||
pe.event_param = c.conference_id
|
||||
ORDER BY pe.time DESC
|
||||
LIMIT 1
|
||||
)
|
||||
)
|
||||
) AS end
|
||||
FROM conferences c
|
||||
JOIN
|
||||
WHERE ce.conference_event = 'bridge selected'
|
||||
GROUP BY ce.conference_id
|
||||
) AS first_event ON c.conference_id = first_event.conference_id
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE (start >= '%s 00:00:00' AND end <= '%s 23:59:59')
|
||||
) AS subquery";
|
||||
WHERE
|
||||
(ce.time >= '%s 00:00:00' AND ce.time <= '%s 23:59:59')
|
||||
AND (ce.conference_event = 'conference created'
|
||||
OR (ce.conference_event = 'bridge selected' AND ce.time = first_event.first_event_time)
|
||||
)";
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
|
|
|
@ -2,10 +2,15 @@
|
|||
|
||||
class Config {
|
||||
|
||||
public function getPlatformDetails($config, $platform_id) {
|
||||
$platformDetails = $config['platforms'][$platform_id];
|
||||
return $platformDetails;
|
||||
}
|
||||
|
||||
// loading the config.js
|
||||
public function getPlatformConfigjs($jitsiUrl, $raw = false) {
|
||||
public function getPlatformConfigjs($platformDetails, $raw = false) {
|
||||
// constructing the URL
|
||||
$configjsFile = $jitsiUrl . '/config.js';
|
||||
$configjsFile = $platformDetails['jitsi_url'] . '/config.js';
|
||||
|
||||
// default content, if we can't get the file contents
|
||||
$platformConfigjs = "The file $configjsFile can't be loaded.";
|
||||
|
@ -45,9 +50,9 @@ class Config {
|
|||
|
||||
|
||||
// loading the interface_config.js
|
||||
public function getPlatformInterfaceConfigjs($jitsiUrl, $raw = false) {
|
||||
public function getPlatformInterfaceConfigjs($platformDetails, $raw = false) {
|
||||
// constructing the URL
|
||||
$interfaceConfigjsFile = $jitsiUrl . '/interface_config.js';
|
||||
$interfaceConfigjsFile = $platformDetails['jitsi_url'] . '/interface_config.js';
|
||||
|
||||
// default content, if we can't get the file contents
|
||||
$platformInterfaceConfigjs = "The file $interfaceConfigjsFile can't be loaded.";
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
require '../app/helpers/errors.php';
|
||||
|
||||
class Database {
|
||||
private $pdo;
|
||||
|
||||
|
@ -42,8 +44,6 @@ class Database {
|
|||
try {
|
||||
$this->pdo = new PDO("sqlite:" . $options['dbFile']);
|
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
// enable foreign key constraints (not ON by default in SQLite3)
|
||||
$this->pdo->exec('PRAGMA foreign_keys = ON;');
|
||||
} catch (PDOException $e) {
|
||||
$error = getError('SQLite connection failed: ', $e->getMessage());
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class Database {
|
|||
$this->pdo = new PDO($dsn, $options['user'], $options['password'] ?? '');
|
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException $e) {
|
||||
$error = getError('MySQL connection failed: ', $e->getMessage(), $config['environment']);
|
||||
$error = getError('MySQL connection failed: ', $config['environment'], $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Log {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
// insert log event
|
||||
public function insertLog($user_id, $message, $scope='user') {
|
||||
try {
|
||||
$sql = 'INSERT INTO logs
|
||||
(user_id, scope, message)
|
||||
VALUES
|
||||
(:user_id, :scope, :message)';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
':scope' => $scope,
|
||||
':message' => $message,
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// read logs
|
||||
public function readLog($user_id, $scope, $offset=0, $items_per_page='') {
|
||||
if ($scope === 'user') {
|
||||
$sql = 'SELECT * FROM logs WHERE user_id = :user_id ORDER BY time DESC';
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
]);
|
||||
}
|
||||
if ($scope === 'system') {
|
||||
$sql = 'SELECT * FROM logs ORDER BY time DESC';
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -9,7 +9,7 @@ class Participant {
|
|||
|
||||
|
||||
// search/list specific participant ID
|
||||
public function conferenceByParticipantId($participant_id, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferenceByParticipantId($participant_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -69,11 +69,6 @@ AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $participant_id, $from_time, $until_time, $participant_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -84,7 +79,7 @@ ORDER BY
|
|||
|
||||
|
||||
// search/list specific participant name (stats_id)
|
||||
public function conferenceByParticipantName($participant_name, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferenceByParticipantName($participant_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -144,11 +139,6 @@ AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $participant_name, $from_time, $until_time, $participant_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -159,7 +149,7 @@ ORDER BY
|
|||
|
||||
|
||||
// search/list specific participant IP
|
||||
public function conferenceByParticipantIP($participant_ip, $from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function conferenceByParticipantIP($participant_ip, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -219,11 +209,6 @@ AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
|||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $participant_ip, $from_time, $until_time, $participant_ip, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
@ -234,7 +219,7 @@ ORDER BY
|
|||
|
||||
|
||||
// list of all participants
|
||||
public function participantsAll($from_time, $until_time, $offset=0, $items_per_page='') {
|
||||
public function participantsAll($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
|
@ -261,11 +246,6 @@ WHERE
|
|||
pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59'
|
||||
ORDER BY p.id";
|
||||
|
||||
if ($items_per_page) {
|
||||
$items_per_page = (int)$items_per_page;
|
||||
$sql .= ' LIMIT ' . $offset . ',' . $items_per_page;
|
||||
}
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Platform {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
// get details of a specified platform ID (or all)
|
||||
public function getPlatformDetails($platform_id = '') {
|
||||
$sql = 'SELECT * FROM platforms';
|
||||
if ($platform_id !== '') {
|
||||
$sql .= ' WHERE id = :platform_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':platform_id', $platform_id);
|
||||
} else {
|
||||
$query = $this->db->prepare($sql);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// add new platform
|
||||
public function addPlatform($newPlatform) {
|
||||
try {
|
||||
$sql = 'INSERT INTO platforms
|
||||
(name, jitsi_url, jilo_database)
|
||||
VALUES
|
||||
(:name, :jitsi_url, :jilo_database)';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':name' => $newPlatform['name'],
|
||||
':jitsi_url' => $newPlatform['jitsi_url'],
|
||||
':jilo_database' => $newPlatform['jilo_database'],
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// edit an existing platform
|
||||
public function editPlatform($platform_id, $updatedPlatform) {
|
||||
try {
|
||||
$sql = 'UPDATE platforms SET
|
||||
name = :name,
|
||||
jitsi_url = :jitsi_url,
|
||||
jilo_database = :jilo_database
|
||||
WHERE
|
||||
id = :platform_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':name' => $updatedPlatform['name'],
|
||||
':jitsi_url' => $updatedPlatform['jitsi_url'],
|
||||
':jilo_database' => $updatedPlatform['jilo_database'],
|
||||
':platform_id' => $platform_id,
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// delete a platform
|
||||
public function deletePlatform($platform_id) {
|
||||
try {
|
||||
$sql = 'DELETE FROM platforms
|
||||
WHERE
|
||||
id = :platform_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':platform_id', $platform_id);
|
||||
|
||||
$query->execute();
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Server {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
// get Jilo Server status
|
||||
public function getServerStatus($host = '127.0.0.1', $port = 8080, $endpoint = '/health') {
|
||||
$url = "http://$host:$port$endpoint";
|
||||
$options = [
|
||||
'http' => [
|
||||
'method' => 'GET',
|
||||
'timeout' => 3,
|
||||
],
|
||||
];
|
||||
$context = stream_context_create($options);
|
||||
$response = @file_get_contents($url, false, $context);
|
||||
|
||||
// We check the response if it's 200 OK
|
||||
if ($response !== false && isset($http_response_header) && strpos($http_response_header[0], '200 OK') !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's not 200 OK
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -9,51 +9,12 @@ class User {
|
|||
|
||||
// registration
|
||||
public function register($username, $password) {
|
||||
try {
|
||||
// we have two inserts, start a transaction
|
||||
$this->db->beginTransaction();
|
||||
|
||||
// hash the password, don't store it plain
|
||||
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
||||
$query = $this->db->prepare("INSERT INTO users (username, password) VALUES (:username, :password)");
|
||||
$query->bindParam(':username', $username);
|
||||
$query->bindParam(':password', $hashedPassword);
|
||||
|
||||
// insert into users table
|
||||
$sql = 'INSERT
|
||||
INTO users (username, password)
|
||||
VALUES (:username, :password)';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindValue(':username', $username);
|
||||
$query->bindValue(':password', $hashedPassword);
|
||||
|
||||
// execute the first query
|
||||
if (!$query->execute()) {
|
||||
// rollback on error
|
||||
$this->db->rollBack();
|
||||
return false;
|
||||
}
|
||||
|
||||
// insert the last user id into users_meta table
|
||||
$sql2 = 'INSERT
|
||||
INTO users_meta (user_id)
|
||||
VALUES (:user_id)';
|
||||
$query2 = $this->db->prepare($sql2);
|
||||
$query2->bindValue(':user_id', $this->db->lastInsertId());
|
||||
|
||||
// execute the second query
|
||||
if (!$query2->execute()) {
|
||||
// rollback on error
|
||||
$this->db->rollBack();
|
||||
return false;
|
||||
}
|
||||
|
||||
// if all is OK, commit the transaction
|
||||
$this->db->commit();
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
// rollback on any error
|
||||
$this->db->rollBack();
|
||||
return $e->getMessage();
|
||||
}
|
||||
return $query->execute();
|
||||
}
|
||||
|
||||
// login
|
||||
|
@ -72,256 +33,6 @@ class User {
|
|||
}
|
||||
}
|
||||
|
||||
// get user ID from username
|
||||
// FIXME not used now?
|
||||
public function getUserId($username) {
|
||||
$sql = 'SELECT id FROM users WHERE username = :username';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->bindParam(':username', $username);
|
||||
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
}
|
||||
|
||||
// get user details
|
||||
public function getUserDetails($user_id) {
|
||||
$sql = 'SELECT
|
||||
um.*,
|
||||
u.username
|
||||
FROM
|
||||
users_meta um
|
||||
LEFT JOIN users u
|
||||
ON um.user_id = u.id
|
||||
WHERE
|
||||
u.id = :user_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
]);
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
}
|
||||
|
||||
// add user right
|
||||
public function addUserRight($user_id, $right_id) {
|
||||
$sql = 'INSERT INTO users_rights
|
||||
(user_id, right_id)
|
||||
VALUES
|
||||
(:user_id, :right_id)';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
':right_id' => $right_id,
|
||||
]);
|
||||
}
|
||||
|
||||
// remove user right
|
||||
public function removeUserRight($user_id, $right_id) {
|
||||
$sql = 'DELETE FROM users_rights
|
||||
WHERE
|
||||
user_id = :user_id
|
||||
AND
|
||||
right_id = :right_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
':right_id' => $right_id,
|
||||
]);
|
||||
}
|
||||
|
||||
// get all rights
|
||||
public function getAllRights() {
|
||||
$sql = 'SELECT
|
||||
id AS right_id,
|
||||
name AS right_name
|
||||
FROM rights
|
||||
ORDER BY id ASC';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
}
|
||||
|
||||
// get user rights
|
||||
public function getUserRights($user_id) {
|
||||
$sql = 'SELECT
|
||||
u.id AS user_id,
|
||||
r.id AS right_id,
|
||||
r.name AS right_name
|
||||
FROM
|
||||
users u
|
||||
LEFT JOIN users_rights ur
|
||||
ON u.id = ur.user_id
|
||||
LEFT JOIN rights r
|
||||
ON ur.right_id = r.id
|
||||
WHERE
|
||||
u.id = :user_id';
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
]);
|
||||
|
||||
$result = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ensure specific entries are included in the result
|
||||
$specialEntries = [];
|
||||
|
||||
// user 1 is always superuser
|
||||
if ($user_id == 1) {
|
||||
$specialEntries = [
|
||||
[
|
||||
'user_id' => 1,
|
||||
'right_id' => 1,
|
||||
'right_name' => 'superuser'
|
||||
]
|
||||
];
|
||||
|
||||
// user 2 is always demo
|
||||
} elseif ($user_id == 2) {
|
||||
$specialEntries = [
|
||||
[
|
||||
'user_id' => 2,
|
||||
'right_id' => 100,
|
||||
'right_name' => 'demo user'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// merge the special entries with the existing results
|
||||
$result = array_merge($specialEntries, $result);
|
||||
// remove duplicates if necessary
|
||||
$result = array_unique($result, SORT_REGULAR);
|
||||
|
||||
// return the modified result
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
// check if the user has a specific right
|
||||
function hasRight($user_id, $right_name) {
|
||||
$userRights = $this->getUserRights($user_id);
|
||||
$userHasRight = false;
|
||||
|
||||
// superuser always has all the rights
|
||||
if ($user_id === 1) {
|
||||
$userHasRight = true;
|
||||
}
|
||||
|
||||
foreach ($userRights as $right) {
|
||||
if ($right['right_name'] === $right_name) {
|
||||
$userHasRight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $userHasRight;
|
||||
|
||||
}
|
||||
|
||||
// update an existing user
|
||||
public function editUser($user_id, $updatedUser) {
|
||||
try {
|
||||
$sql = 'UPDATE users_meta SET
|
||||
name = :name,
|
||||
email = :email,
|
||||
timezone = :timezone,
|
||||
bio = :bio
|
||||
WHERE user_id = :user_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
':name' => $updatedUser['name'],
|
||||
':email' => $updatedUser['email'],
|
||||
':timezone' => $updatedUser['timezone'],
|
||||
':bio' => $updatedUser['bio']
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remove an avatar
|
||||
public function removeAvatar($user_id, $old_avatar = '') {
|
||||
try {
|
||||
// remove from database
|
||||
$sql = 'UPDATE users_meta SET
|
||||
avatar = NULL
|
||||
WHERE user_id = :user_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
]);
|
||||
|
||||
// delete the old avatar file
|
||||
if ($old_avatar && file_exists($old_avatar)) {
|
||||
unlink($old_avatar);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// change an avatar
|
||||
public function changeAvatar($user_id, $avatar_file, $avatars_path) {
|
||||
try {
|
||||
// check if the file was uploaded
|
||||
if (isset($avatar_file) && $avatar_file['error'] === UPLOAD_ERR_OK) {
|
||||
$fileTmpPath = $avatar_file['tmp_name'];
|
||||
$fileName = $avatar_file['name'];
|
||||
$fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
|
||||
// validate file extension
|
||||
if (in_array($fileExtension, ['jpg', 'png', 'jpeg'])) {
|
||||
$newFileName = md5(time() . $fileName) . '.' . $fileExtension;
|
||||
$dest_path = $avatars_path . $newFileName;
|
||||
|
||||
// move the file to avatars folder
|
||||
if (move_uploaded_file($fileTmpPath, $dest_path)) {
|
||||
try {
|
||||
// update user's avatar path in DB
|
||||
$sql = 'UPDATE users_meta SET
|
||||
avatar = :avatar
|
||||
WHERE user_id = :user_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':avatar' => $newFileName,
|
||||
':user_id' => $user_id
|
||||
]);
|
||||
// all went OK
|
||||
$_SESSION['notice'] .= 'Avatar updated successfully. ';
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Error moving the uploaded file. ';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Invalid avatar file type. ';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Error uploading the avatar file. ';
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -26,15 +26,32 @@ return [
|
|||
// default is ../app/jilo-web.db
|
||||
'sqlite_file' => '../app/jilo-web.db',
|
||||
],
|
||||
// avatars path
|
||||
'avatars_path' => 'uploads/avatars/',
|
||||
// default avatar
|
||||
'default_avatar' => 'static/default_avatar.png',
|
||||
// system info
|
||||
'version' => '0.2.1',
|
||||
'version' => '0.2',
|
||||
// development has verbose error messages, production has not
|
||||
'environment' => 'development',
|
||||
|
||||
// *************************************
|
||||
// Maintained by the app, edit with care
|
||||
// *************************************
|
||||
|
||||
'platforms' => [
|
||||
'0' => [
|
||||
'name' => 'lindeas',
|
||||
'jitsi_url' => 'https://meet.lindeas.com',
|
||||
'jilo_database' => '../../jilo/jilo-meet.lindeas.db',
|
||||
],
|
||||
'1' => [
|
||||
'name' => 'meet.example.com',
|
||||
'jitsi_url' => 'https://meet.example.com',
|
||||
'jilo_database' => '../../jilo/jilo.db',
|
||||
],
|
||||
'2' => [
|
||||
'name' => 'test3',
|
||||
'jitsi_url' => 'https://test3.example.com',
|
||||
'jilo_database' => '../../jilo/jilo2.db',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
// Function to format arrays with square brackets
|
||||
function formatArray(array $array, $indentLevel = 2) {
|
||||
$indent = str_repeat(' ', $indentLevel); // 4 spaces per indent level
|
||||
$output = "[\n";
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
$output .= $indent . "'" . $key . "'" . ' => ';
|
||||
|
||||
if (is_array($value)) {
|
||||
$output .= formatArray($value, $indentLevel + 1);
|
||||
} else {
|
||||
$output .= var_export($value, true);
|
||||
}
|
||||
|
||||
$output .= ",\n";
|
||||
}
|
||||
|
||||
$output .= str_repeat(' ', $indentLevel - 1) . ']';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
// connect to database
|
||||
function connectDB($config, $database = '', $dbFile = '', $platformId = '') {
|
||||
function connectDB($config, $database = '', $platform_id = '') {
|
||||
|
||||
// connecting ti a jilo sqlite database
|
||||
if ($database === 'jilo') {
|
||||
try {
|
||||
$dbFile = $config['platforms'][$platform_id]['jilo_database'] ?? null;
|
||||
if (!$dbFile || !file_exists($dbFile)) {
|
||||
throw new Exception(getError("Invalid platform ID \"{$platformId}\", database file \"{$dbFile}\" not found."));
|
||||
throw new Exception(getError("Invalid platform ID \"{$platform_id}\", database file \"{$dbFile}\"not found."));
|
||||
}
|
||||
$db = new Database([
|
||||
'type' => 'sqlite',
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
<div style="position: relative; width: 800px; height: 400px;">
|
||||
<div id="current-period-<?= $data['graph_name'] ?>" style="text-align: center; position: absolute; top: 0; left: 0; right: 0; z-index: 10; font-size: 14px; background-color: rgba(255, 255, 255, 0.7);"></div>
|
||||
<canvas id="graph_<?= $data['graph_name'] ?>" style="margin-top: 20px; margin-bottom: 50px;"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ctx = document.getElementById('graph_<?= $data['graph_name'] ?>').getContext('2d');
|
||||
var chartData0 = <?php echo json_encode($data['data0']); ?>;
|
||||
var chartData1 = <?php echo json_encode($data['data1']); ?>;
|
||||
var timeRangeName = '';
|
||||
|
||||
var labels = chartData0.map(function(item) {
|
||||
return item.date;
|
||||
});
|
||||
var values0 = chartData0.map(function(item) {
|
||||
return item.value;
|
||||
});
|
||||
var values1 = chartData1.map(function(item) {
|
||||
return item.value;
|
||||
});
|
||||
|
||||
var graph_<?= $data['graph_name'] ?> = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: '<?= $data['graph_data0_label'] ?? '' ?>',
|
||||
data: values0,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false
|
||||
},
|
||||
{
|
||||
label: '<?= $data['graph_data1_label'] ?? '' ?>',
|
||||
data: values1,
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
layout: {
|
||||
padding: {
|
||||
top: 30
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'day'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
zoom: {
|
||||
// enabled: true,
|
||||
mode: 'x',
|
||||
drag: {
|
||||
enabled: true, // Enable drag to select range
|
||||
borderColor: 'rgba(255, 99, 132, 0.3)',
|
||||
borderWidth: 1
|
||||
},
|
||||
onZoom: function({ chart }) {
|
||||
propagateZoom(chart); // Propagate the zoom to all graphs
|
||||
setActive(document.getElementById('custom_range'));
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 20,
|
||||
padding: 10
|
||||
}
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $data['graph_title'] ?>',
|
||||
font: {
|
||||
size: 16,
|
||||
weight: 'bold'
|
||||
},
|
||||
padding: {
|
||||
bottom: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Store the graphs in an array
|
||||
graphs.push({
|
||||
graph: graph_<?= $data['graph_name'] ?>,
|
||||
label: document.getElementById('current-period-<?= $data['graph_name'] ?>')
|
||||
});
|
||||
|
||||
// Update the time range label
|
||||
function updatePeriodLabel(chart, labelElement) {
|
||||
var startDate = chart.scales.x.min;
|
||||
var endDate = chart.scales.x.max;
|
||||
if (timeRangeName == 'today') {
|
||||
labelElement.innerHTML = 'Currently displaying: ' + timeRangeName + ' (' + new Date(startDate).toLocaleDateString() + ')';
|
||||
} else {
|
||||
labelElement.innerHTML = 'Currently displaying: ' + timeRangeName + ' (' + new Date(startDate).toLocaleDateString() + ' - ' + new Date(endDate).toLocaleDateString() + ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Attach the update function to the 'zoom' event
|
||||
graph_<?= $data['graph_name'] ?>.options.plugins.zoom.onZoom = function({ chart }) {
|
||||
updatePeriodLabel(chart, document.getElementById('current-period-<?= $data['graph_name'] ?>'));
|
||||
};
|
||||
|
||||
// Update the label initially when the chart is rendered
|
||||
updatePeriodLabel(graph_<?= $data['graph_name'] ?>, document.getElementById('current-period-<?= $data['graph_name'] ?>'));
|
||||
|
||||
</script>
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
function getUserIP() {
|
||||
// get directly the user IP
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
// if user is behind some proxy
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
// get only the first IP if there are more
|
||||
if (strpos($ip, ',') !== false) {
|
||||
$ip = explode(',', $ip)[0];
|
||||
}
|
||||
|
||||
return trim($ip);
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,81 +0,0 @@
|
|||
|
||||
<div class="text-center">
|
||||
<div class="pagination">
|
||||
<?php
|
||||
$param = '';
|
||||
if (isset($_REQUEST['id'])) {
|
||||
$param .= '&id=' . htmlspecialchars($_REQUEST['id']);
|
||||
}
|
||||
if (isset($_REQUEST['name'])) {
|
||||
$param .= '&name=' . htmlspecialchars($_REQUEST['name']);
|
||||
}
|
||||
if (isset($_REQUEST['ip'])) {
|
||||
$param .= '&ip=' . htmlspecialchars($_REQUEST['ip']);
|
||||
}
|
||||
if (isset($_REQUEST['event'])) {
|
||||
$param .= '&event=' . htmlspecialchars($_REQUEST['event']);
|
||||
}
|
||||
if (isset($_REQUEST['from_time'])) {
|
||||
$param .= '&from_time=' . htmlspecialchars($from_time);
|
||||
}
|
||||
if (isset($_REQUEST['until_time'])) {
|
||||
$param .= '&until_time=' . htmlspecialchars($until_time);
|
||||
}
|
||||
|
||||
$max_visible_pages = 10;
|
||||
$step_pages = 10;
|
||||
|
||||
if ($browse_page > 1) {
|
||||
echo '<span><a href="' . htmlspecialchars($url) . '&p=1">first</a></span>';
|
||||
} else {
|
||||
echo '<span>first</span>';
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= $page_count; $i++) {
|
||||
// always show the first, last, step pages (10, 20, 30, etc.),
|
||||
// and the pages close to the current one
|
||||
if (
|
||||
$i === 1 || // first page
|
||||
$i === $page_count || // last page
|
||||
$i === $browse_page || // current page
|
||||
$i === $browse_page -1 ||
|
||||
$i === $browse_page +1 ||
|
||||
$i === $browse_page -2 ||
|
||||
$i === $browse_page +2 ||
|
||||
($i % $step_pages === 0 && $i > $max_visible_pages) // the step pages - 10, 20, etc.
|
||||
) {
|
||||
if ($i === $browse_page) {
|
||||
// current page, no link
|
||||
if ($browse_page > 1) {
|
||||
echo '<span><a href="' . htmlspecialchars($app_root) . '?platform=' . htmlspecialchars($platform_id) . '&page=' . htmlspecialchars($page) . $param . '&p=' . (htmlspecialchars($browse_page) -1) . '"><<</a></span>';
|
||||
} else {
|
||||
echo '<span><<</span>';
|
||||
}
|
||||
echo '[' . htmlspecialchars($i) . ']';
|
||||
|
||||
if ($browse_page < $page_count) {
|
||||
echo '<span><a href="' . htmlspecialchars($app_root) . '?platform=' . htmlspecialchars($platform_id) . '&page=' . htmlspecialchars($page) . $param . '&p=' . (htmlspecialchars($browse_page) +1) . '">>></a></span>';
|
||||
} else {
|
||||
echo '<span>>></span>';
|
||||
}
|
||||
} else {
|
||||
// other pages
|
||||
echo '<span><a href="' . htmlspecialchars($app_root) . '?platform=' . htmlspecialchars($platform_id) . '&page=' . htmlspecialchars($page) . $param . '&p=' . htmlspecialchars($i) . '">[' . htmlspecialchars($i) . ']</a></span>';
|
||||
}
|
||||
// show ellipses between distant pages
|
||||
} elseif (
|
||||
$i === $browse_page -3 ||
|
||||
$i === $browse_page +3
|
||||
) {
|
||||
echo '<span>...</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($browse_page < $page_count) {
|
||||
echo '<span><a href="' . htmlspecialchars($app_root) . '?platform=' . htmlspecialchars($platform_id) . '&page=' . htmlspecialchars($page) . $param . '&p=' . (htmlspecialchars($page_count)) . '">last</a></span>';
|
||||
} else {
|
||||
echo '<span>last</span>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
// get the UTC offset of a specified timezone
|
||||
function getUTCOffset($timezone) {
|
||||
$formattedOffset = '';
|
||||
if (isset($timezone)) {
|
||||
|
||||
$datetime = new DateTime("now", new DateTimeZone($timezone));
|
||||
$offsetInSeconds = $datetime->getOffset();
|
||||
|
||||
$hours = intdiv($offsetInSeconds, 3600);
|
||||
$minutes = ($offsetInSeconds % 3600) / 60;
|
||||
$formattedOffset = sprintf("UTC%+03d:%02d", $hours, $minutes); // Format UTC+01:00
|
||||
}
|
||||
|
||||
return $formattedOffset;
|
||||
|
||||
}
|
||||
|
||||
// switch platforms
|
||||
function switchPlatform($platform_id) {
|
||||
// get the current URL and parse it
|
||||
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
||||
$current_url = "$scheme://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
|
||||
$url_components = parse_url($current_url);
|
||||
|
||||
// parse query parameters if they exist
|
||||
parse_str($url_components['query'] ?? '', $query_params);
|
||||
|
||||
// check if the 'platform' parameter is set
|
||||
if (isset($query_params['platform'])) {
|
||||
// change the platform to the new platform_id
|
||||
$query_params['platform'] = $platform_id;
|
||||
$new_query_string = http_build_query($query_params);
|
||||
|
||||
// there is no 'platform', we redirect to front page of the new platform_id
|
||||
} else {
|
||||
$new_query_string = 'platform=' . $platform_id;
|
||||
}
|
||||
|
||||
// rebuild the query and the URL
|
||||
$new_url = $scheme . '://' . $url_components['host'] . $url_components['path'] . '?' . $new_query_string;
|
||||
|
||||
// return the new URL with the new platform_id
|
||||
return $new_url;
|
||||
}
|
||||
|
||||
?>
|
|
@ -4,14 +4,40 @@
|
|||
function renderConfig($configPart, $indent, $platform=false, $parent='') {
|
||||
global $app_root;
|
||||
global $config;
|
||||
if ($parent === 'platforms') {
|
||||
?>
|
||||
<div class="col-md-8 text-start">
|
||||
<a class="btn btn-secondary" style="padding: 0px;" href="<?= $app_root ?>?page=config&action=add">add</a>
|
||||
</div>
|
||||
<div class="border bg-light" style="padding-left: <?= $indent ?>px; padding-bottom: 20px; padding-top: 20px;">
|
||||
<?php } else {
|
||||
?>
|
||||
<div style="padding-left: <?= $indent ?>px; padding-bottom: 20px;">
|
||||
<?php foreach ($configPart as $config_item => $config_value) { ?>
|
||||
<?php
|
||||
}
|
||||
foreach ($configPart as $config_item => $config_value) {
|
||||
if ($parent === 'platforms') {
|
||||
$indent = 0;
|
||||
}
|
||||
?>
|
||||
<div class="row mb-1" style="padding-left: <?= $indent ?>px;">
|
||||
<div class="col-md-4 text-end">
|
||||
<?= htmlspecialchars($config_item) ?>:
|
||||
</div>
|
||||
<?php
|
||||
if ($parent === 'platforms') { ?>
|
||||
<div class="col-md-8 text-start">
|
||||
<a class="btn btn-secondary" style="padding: 2px;" href="<?= $app_root ?>?platform=<?= htmlspecialchars($config_item) ?>&page=config&action=edit">edit</a>
|
||||
<?php
|
||||
// we don't delete the last platform
|
||||
if (count($configPart) <= 1) { ?>
|
||||
<span class="btn btn-light" style="padding: 2px;" href="#" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="can't delete the last platform">delete</span>
|
||||
<?php } else { ?>
|
||||
<a class="btn btn-danger" style="padding: 2px;" href="<?= $app_root ?>?platform=<?= htmlspecialchars($config_item) ?>&page=config&action=delete">delete</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php }
|
||||
|
||||
if (is_array($config_value)) {
|
||||
// here we render recursively nested arrays
|
||||
$indent = $indent + 50;
|
||||
|
@ -29,11 +55,15 @@ function renderConfig($configPart, $indent, $platform=false, $parent='') {
|
|||
?>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($config_value ?? '')?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?= $platform ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
// sanitize all input vars that may end up in URLs or forms
|
||||
|
||||
$platform_id = htmlspecialchars($_REQUEST['platform']);
|
||||
if (isset($_REQUEST['page'])) {
|
||||
$page = htmlspecialchars($_REQUEST['page']);
|
||||
} else {
|
||||
$page = 'dashboard';
|
||||
}
|
||||
if (isset($_REQUEST['item'])) {
|
||||
$item = htmlspecialchars($_REQUEST['item']);
|
||||
} else {
|
||||
$item = '';
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['from_time'])) {
|
||||
$from_time = htmlspecialchars($_REQUEST['from_time']);
|
||||
}
|
||||
if (isset($_REQUEST['until_time'])) {
|
||||
$until_time = htmlspecialchars($_REQUEST['until_time']);
|
||||
}
|
||||
|
||||
if (isset($_SESSION['notice'])) {
|
||||
$notice = htmlspecialchars($_SESSION['notice']); // 'notice' for all non-critical messages
|
||||
}
|
||||
if (isset($_SESSION['error'])) {
|
||||
$error = htmlspecialchars($_SESSION['error']); // 'error' for errors
|
||||
}
|
||||
|
||||
// agents
|
||||
if (isset($_POST['type'])) {
|
||||
$type = htmlspecialchars($_POST['type']);
|
||||
}
|
||||
if (isset($_POST['url'])) {
|
||||
$url = htmlspecialchars($_POST['url']);
|
||||
}
|
||||
if (isset($_POST['secret_key'])) {
|
||||
$secret_key = htmlspecialchars($_POST['secret_key']);
|
||||
}
|
||||
if (isset($_POST['check_period'])) {
|
||||
$check_period = htmlspecialchars($_POST['check_period']);
|
||||
}
|
||||
|
||||
// platforms
|
||||
if (isset($_POST['name'])) {
|
||||
$name = htmlspecialchars($_POST['name']);
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -1,14 +1,16 @@
|
|||
<?php
|
||||
|
||||
$time_range_specified = false;
|
||||
if (!isset($from_time) || (isset($from_time) && $from_time == '')) {
|
||||
if (!isset($_REQUEST['from_time']) || (isset($_REQUEST['from_time']) && $_REQUEST['from_time'] == '')) {
|
||||
$from_time = '0000-01-01';
|
||||
} else {
|
||||
$from_time = $_REQUEST['from_time'];
|
||||
$time_range_specified = true;
|
||||
}
|
||||
if (!isset($until_time) || (isset($until_time) && $until_time == '')) {
|
||||
if (!isset($_REQUEST['until_time']) || (isset($_REQUEST['until_time']) && $_REQUEST['until_time'] == '')) {
|
||||
$until_time = '9999-12-31';
|
||||
} else {
|
||||
$until_time = $_REQUEST['until_time'];
|
||||
$time_range_specified = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
|
||||
$action = $_REQUEST['action'] ?? '';
|
||||
$agent = $_REQUEST['agent'] ?? '';
|
||||
require '../app/classes/agent.php';
|
||||
|
||||
$agentObject = new Agent($dbWeb);
|
||||
|
||||
// if it's a POST request, it's saving to cache
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
// read the JSON sent from javascript
|
||||
$data = file_get_contents("php://input");
|
||||
$result = json_decode($data, true);
|
||||
|
||||
// store the data in the session
|
||||
if ($result) {
|
||||
$_SESSION["agent{$agent}_cache"] = $result;
|
||||
$_SESSION["agent{$agent}_cache_time"] = time(); // store the cache time
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => "Cache for agent {$agent} is stored."
|
||||
]);
|
||||
} elseif ($result === null && !empty($agent)) {
|
||||
unset($_SESSION["agent{$agent}_cache"]);
|
||||
unset($_SESSION["agent{$agent}_cache_time"]);
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => "Cache for agent {$agent} is cleared."
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid data'
|
||||
]);
|
||||
}
|
||||
|
||||
//// if it's a GET request, it's read/load from cache
|
||||
//} elseif ($loadcache === true) {
|
||||
//
|
||||
// // check if cached data exists in session
|
||||
// if (isset($_SESSION["agent{$agent}_cache"])) {
|
||||
// // return the cached data in JSON format
|
||||
// echo json_encode(['status' => 'success', 'data' => $_SESSION["agent{$agent}_cache"]]);
|
||||
// } else {
|
||||
// // if no cached data exists
|
||||
// echo json_encode(['status' => 'error', 'message' => 'No cached data found']);
|
||||
// }
|
||||
|
||||
// no form submitted, show the templates
|
||||
} else {
|
||||
$agentDetails = $agentObject->getAgentDetails($platform_id);
|
||||
include '../app/templates/agent-list.php';
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,19 +1,28 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/component.php';
|
||||
|
||||
// connect to database
|
||||
$db = connectDB($config, 'jilo', $platformDetails[0]['jilo_database'], $platform_id);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
// specify time range
|
||||
include '../app/helpers/time_range.php';
|
||||
|
||||
// jitsi component events list
|
||||
// we use $_REQUEST, so that both links and forms work
|
||||
// if it's there, but empty, we make it same as the field name; otherwise assign the value
|
||||
$jitsi_component = !empty($_REQUEST['name']) ? "'" . $_REQUEST['name'] . "'" : 'jitsi_component';
|
||||
$component_id = !empty($_REQUEST['id']) ? "'" . $_REQUEST['id'] . "'" : 'component_id';
|
||||
$event_type = !empty($_REQUEST['event']) ? "'" . $_REQUEST['event'] . "'" : 'event_type';
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
$jitsi_component = "'" . $_REQUEST['name'] . "'";
|
||||
$component_id = 'component_id';
|
||||
} elseif (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$component_id = "'" . $_REQUEST['id'] . "'";
|
||||
$jitsi_component = 'jitsi_component';
|
||||
} else {
|
||||
// we need the variables to use them later in sql for columnname = columnname
|
||||
$jitsi_component = 'jitsi_component';
|
||||
$component_id = 'component_id';
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
@ -22,23 +31,12 @@ $event_type = !empty($_REQUEST['event']) ? "'" . $_REQUEST['event'] . "'" : 'eve
|
|||
|
||||
|
||||
// list of all component events (default)
|
||||
$componentObject = new Component($db);
|
||||
|
||||
// pagination variables
|
||||
$items_per_page = 15;
|
||||
$browse_page = $_REQUEST['p'] ?? 1;
|
||||
$browse_page = (int)$browse_page;
|
||||
$offset = ($browse_page -1) * $items_per_page;
|
||||
$component = new Component($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $componentObject->jitsiComponents($jitsi_component, $component_id, $event_type, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $componentObject->jitsiComponents($jitsi_component, $component_id, $event_type, $from_time, $until_time);
|
||||
$search = $component->jitsiComponents($jitsi_component, $component_id, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
// we get total items and number of pages
|
||||
$item_count = count($search_all);
|
||||
$page_count = ceil($item_count / $items_per_page);
|
||||
|
||||
$components = array();
|
||||
$components['records'] = array();
|
||||
|
||||
|
@ -61,8 +59,9 @@ if (!empty($search)) {
|
|||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'AllComponents';
|
||||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
$widget['pagination'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
|
@ -80,6 +79,6 @@ if (!empty($components['records'])) {
|
|||
}
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/event-list-components.php';
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/conference.php';
|
||||
|
||||
// connect to database
|
||||
$db = connectDB($config, 'jilo', $platformDetails[0]['jilo_database'], $platform_id);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
// specify time range
|
||||
include '../app/helpers/time_range.php';
|
||||
|
||||
// conference id/name are specified when searching specific conference(s)
|
||||
// either id OR name, id has precedence
|
||||
// we use $_REQUEST, so that both links and forms work
|
||||
// if it's there, but empty, we make it same as the field name; otherwise assign the value
|
||||
|
||||
//$conferenceName = !empty($_REQUEST['name']) ? "'" . $_REQUEST['name'] . "'" : 'conference_name';
|
||||
//$conferenceId = !empty($_REQUEST['id']) ? "'" . $_REQUEST['id'] . "'" : 'conference_id';
|
||||
|
||||
if (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$conferenceId = $_REQUEST['id'];
|
||||
unset($_REQUEST['name']);
|
||||
|
@ -33,33 +31,20 @@ if (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
|||
//
|
||||
|
||||
|
||||
$conferenceObject = new Conference($db);
|
||||
|
||||
// pagination variables
|
||||
$items_per_page = 15;
|
||||
$browse_page = $_REQUEST['p'] ?? 1;
|
||||
$browse_page = (int)$browse_page;
|
||||
$offset = ($browse_page -1) * $items_per_page;
|
||||
$conference = new Conference($db);
|
||||
|
||||
// search and list specific conference ID
|
||||
if (isset($conferenceId)) {
|
||||
$search = $conferenceObject->conferenceById($conferenceId, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $conferenceObject->conferenceById($conferenceId, $from_time, $until_time);
|
||||
$search = $conference->conferenceById($conferenceId, $from_time, $until_time);
|
||||
// search and list specific conference name
|
||||
} elseif (isset($conferenceName)) {
|
||||
$search = $conferenceObject->conferenceByName($conferenceName, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $conferenceObject->conferenceByName($conferenceName, $from_time, $until_time);
|
||||
$search = $conference->conferenceByName($conferenceName, $from_time, $until_time);
|
||||
// list of all conferences (default)
|
||||
} else {
|
||||
$search = $conferenceObject->conferencesAllFormatted($from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $conferenceObject->conferencesAllFormatted($from_time, $until_time);
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
// we get total items and number of pages
|
||||
$item_count = count($search_all);
|
||||
$page_count = ceil($item_count / $items_per_page);
|
||||
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
|
@ -126,7 +111,6 @@ $widget['name'] = 'Conferences';
|
|||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
$widget['pagination'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
|
@ -144,6 +128,6 @@ if (!empty($conferences['records'])) {
|
|||
}
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/event-list-conferences.php';
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,105 +1,98 @@
|
|||
<?php
|
||||
|
||||
$action = $_REQUEST['action'] ?? '';
|
||||
$agent = $_REQUEST['agent'] ?? '';
|
||||
require_once '../app/classes/config.php';
|
||||
require '../app/helpers/errors.php';
|
||||
require '../app/helpers/config.php';
|
||||
|
||||
require '../app/classes/config.php';
|
||||
require '../app/classes/agent.php';
|
||||
|
||||
$configObject = new Config();
|
||||
$agentObject = new Agent($dbWeb);
|
||||
$configure = new Config();
|
||||
|
||||
// if a form is submitted, it's from the edit page
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
// FIXME - if editing the flat file is no more needed, remove this
|
||||
// // load the config file and initialize a copy
|
||||
// $content = file_get_contents($config_file);
|
||||
// $updatedContent = $content;
|
||||
|
||||
// new agent adding
|
||||
if (isset($_POST['new']) && isset($_POST['item']) && $_POST['new'] === 'true' && $_POST['item'] === 'agent') {
|
||||
$newAgent = [
|
||||
'type_id' => $type,
|
||||
'url' => $url,
|
||||
'secret_key' => $secret_key,
|
||||
'check_period' => $check_period,
|
||||
];
|
||||
$result = $agentObject->addAgent($platform_id, $newAgent);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] = "New Jilo Agent added.";
|
||||
} else {
|
||||
$_SESSION['error'] = "Adding the agent failed. Error: $result";
|
||||
}
|
||||
// load the config file and initialize a copy
|
||||
$content = file_get_contents($config_file);
|
||||
$updatedContent = $content;
|
||||
|
||||
// new platform adding
|
||||
} elseif (isset($_POST['new']) && $_POST['new'] === 'true') {
|
||||
if (isset($_POST['new']) && $_POST['new'] === 'true') {
|
||||
$newPlatform = [
|
||||
'name' => $name,
|
||||
'name' => $_POST['name'],
|
||||
'jitsi_url' => $_POST['jitsi_url'],
|
||||
'jilo_database' => $_POST['jilo_database'],
|
||||
];
|
||||
$platformObject->addPlatform($newPlatform);
|
||||
|
||||
// deleting an agent
|
||||
} elseif (isset($_POST['delete']) && isset($_POST['agent']) && $_POST['delete'] === 'true') {
|
||||
$result = $agentObject->deleteAgent($agent);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] = "Agent id \"{$_REQUEST['agent']}\" deleted.";
|
||||
} else {
|
||||
$_SESSION['error'] = "Deleting the agent failed. Error: $result";
|
||||
}
|
||||
// Determine the next available index for the new platform
|
||||
$nextIndex = count($config['platforms']);
|
||||
|
||||
// Add the new platform to the platforms array
|
||||
$config['platforms'][$nextIndex] = $newPlatform;
|
||||
|
||||
// Rebuild the PHP array syntax for the platforms
|
||||
$platformsArray = formatArray($config['platforms']);
|
||||
|
||||
// Replace the platforms section in the config file
|
||||
$updatedContent = preg_replace(
|
||||
'/\'platforms\'\s*=>\s*\[[\s\S]+?\],/s',
|
||||
"'platforms' => {$platformsArray}",
|
||||
$content
|
||||
);
|
||||
$updatedContent = preg_replace('/\s*\]\n/s', "\n", $updatedContent);
|
||||
|
||||
// deleting a platform
|
||||
} elseif (isset($_POST['delete']) && $_POST['delete'] === 'true') {
|
||||
$platform = $_POST['platform'];
|
||||
$platformObject->deletePlatform($platform);
|
||||
|
||||
// an update to an existing agent
|
||||
} elseif (isset($_POST['agent'])) {
|
||||
$updatedAgent = [
|
||||
'id' => $agent,
|
||||
'agent_type_id' => $type,
|
||||
'url' => $url,
|
||||
'secret_key' => $secret_key,
|
||||
'check_period' => $check_period,
|
||||
];
|
||||
$result = $agentObject->editAgent($platform_id, $updatedAgent);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] = "Agent id \"{$_REQUEST['agent']}\" edited.";
|
||||
} else {
|
||||
$_SESSION['error'] = "Editing the agent failed. Error: $result";
|
||||
}
|
||||
$config['platforms'][$platform]['name'] = $_POST['name'];
|
||||
$config['platforms'][$platform]['jitsi_url'] = $_POST['jitsi_url'];
|
||||
$config['platforms'][$platform]['jilo_database'] = $_POST['jilo_database'];
|
||||
|
||||
$platformsArray = formatArray($config['platforms'][$platform], 3);
|
||||
|
||||
$updatedContent = preg_replace(
|
||||
"/\s*'$platform'\s*=>\s*\[\s*'name'\s*=>\s*'[^']*',\s*'jitsi_url'\s*=>\s*'[^']*,\s*'jilo_database'\s*=>\s*'[^']*',\s*\],/s",
|
||||
"",
|
||||
$content
|
||||
);
|
||||
|
||||
|
||||
// an update to an existing platform
|
||||
} else {
|
||||
|
||||
$platform = $_POST['platform'];
|
||||
$updatedPlatform = [
|
||||
'name' => $name,
|
||||
'jitsi_url' => $_POST['jitsi_url'],
|
||||
'jilo_database' => $_POST['jilo_database'],
|
||||
];
|
||||
$platformObject->editPlatform($platform, $updatedPlatform);
|
||||
|
||||
$config['platforms'][$platform]['name'] = $_POST['name'];
|
||||
$config['platforms'][$platform]['jitsi_url'] = $_POST['jitsi_url'];
|
||||
$config['platforms'][$platform]['jilo_database'] = $_POST['jilo_database'];
|
||||
|
||||
$platformsArray = formatArray($config['platforms'][$platform], 3);
|
||||
|
||||
$updatedContent = preg_replace(
|
||||
"/\s*'$platform'\s*=>\s*\[\s*'name'\s*=>\s*'[^']*',\s*'jitsi_url'\s*=>\s*'[^']*',\s*'jilo_database'\s*=>\s*'[^']*',\s*\],/s",
|
||||
"\n '{$platform}' => {$platformsArray},",
|
||||
$content
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// FIXME - if this is not needed for editing the flat file, remove it
|
||||
// // check if file is writable
|
||||
// if (!is_writable($config_file)) {
|
||||
// $_SESSION['error'] = getError('Configuration file is not writable.');
|
||||
// header("Location: $app_root?platform=$platform_id&page=config");
|
||||
// exit();
|
||||
// }
|
||||
//
|
||||
// // try to update the config file
|
||||
// if (file_put_contents($config_file, $updatedContent) !== false) {
|
||||
// // update successful
|
||||
// $_SESSION['notice'] = "Configuration for {$_POST['name']} is updated.";
|
||||
// } else {
|
||||
// // unsuccessful
|
||||
// $error = error_get_last();
|
||||
// $_SESSION['error'] = getError('Error updating the config: ' . ($error['message'] ?? 'unknown error'));
|
||||
// }
|
||||
|
||||
|
||||
// check if file is writable
|
||||
if (!is_writable($config_file)) {
|
||||
$_SESSION['error'] = getError('Configuration file is not writable.');
|
||||
header("Location: $app_root?platform=$platform_id&page=config");
|
||||
exit();
|
||||
}
|
||||
|
||||
// try to update the config file
|
||||
if (file_put_contents($config_file, $updatedContent) !== false) {
|
||||
// update successful
|
||||
$_SESSION['notice'] = "Configuration for {$_POST['name']} is updated.";
|
||||
} else {
|
||||
// unsuccessful
|
||||
$error = error_get_last();
|
||||
$_SESSION['error'] = getError('Error updating the config: ' . ($error['message'] ?? 'unknown error'));
|
||||
}
|
||||
|
||||
// FIXME the new file is not loaded on first page load
|
||||
unset($config);
|
||||
|
@ -114,51 +107,32 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|||
case 'configjs':
|
||||
$mode = $_REQUEST['mode'] ?? '';
|
||||
$raw = ($mode === 'raw');
|
||||
$platformConfigjs = $configObject->getPlatformConfigjs($platformDetails[0]['jitsi_url'], $raw);
|
||||
include '../app/templates/config-list-configjs.php';
|
||||
$platformDetails = $configure->getPlatformDetails($config, $platform_id);
|
||||
$platformConfigjs = $configure->getPlatformConfigjs($platformDetails, $raw);
|
||||
include('../app/templates/config-list-configjs.php');
|
||||
break;
|
||||
case 'interfaceconfigjs':
|
||||
$mode = $_REQUEST['mode'] ?? '';
|
||||
$raw = ($mode === 'raw');
|
||||
$platformInterfaceConfigjs = $configObject->getPlatformInterfaceConfigjs($platformDetails[0]['jitsi_url'], $raw);
|
||||
include '../app/templates/config-list-interfaceconfigjs.php';
|
||||
$platformDetails = $configure->getPlatformDetails($config, $platform_id);
|
||||
$platformInterfaceConfigjs = $configure->getPlatformInterfaceConfigjs($platformDetails, $raw);
|
||||
include('../app/templates/config-list-interfaceconfigjs.php');
|
||||
break;
|
||||
|
||||
// if there is no $item, we work on the local config DB
|
||||
// if there is no $item, we work on the local config file
|
||||
default:
|
||||
switch ($action) {
|
||||
case 'add-agent':
|
||||
$jilo_agent_types = $agentObject->getAgentTypes();
|
||||
$jilo_agents_in_platform = $agentObject->getPlatformAgentTypes($platform_id);
|
||||
$jilo_agent_types_in_platform = array_column($jilo_agents_in_platform, 'agent_type_id');
|
||||
include '../app/templates/config-add-agent.php';
|
||||
break;
|
||||
case 'add':
|
||||
include '../app/templates/config-add-platform.php';
|
||||
include('../app/templates/config-add-platform.php');
|
||||
break;
|
||||
case 'edit':
|
||||
if (isset($_GET['agent'])) {
|
||||
$agentDetails = $agentObject->getAgentDetails($platform_id, $agent);
|
||||
$jilo_agent_types = $agentObject->getAgentTypes();
|
||||
include '../app/templates/config-edit-agent.php';
|
||||
} else {
|
||||
include '../app/templates/config-edit-platform.php';
|
||||
}
|
||||
include('../app/templates/config-edit-platform.php');
|
||||
break;
|
||||
case 'delete':
|
||||
if (isset($_GET['agent'])) {
|
||||
$agentDetails = $agentObject->getAgentDetails($platform_id, $agent);
|
||||
include '../app/templates/config-delete-agent.php';
|
||||
} else {
|
||||
include '../app/templates/config-delete-platform.php';
|
||||
}
|
||||
include('../app/templates/config-delete-platform.php');
|
||||
break;
|
||||
default:
|
||||
if ($userObject->hasRight($user_id, 'view config file')) {
|
||||
include '../app/templates/config-list.php';
|
||||
} else {
|
||||
include '../app/templates/error-unauthorized.php';
|
||||
}
|
||||
include('../app/templates/config-list.php');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/conference.php';
|
||||
require '../app/classes/participant.php';
|
||||
|
||||
// connect to database
|
||||
$db = connectDB($config, 'jilo', $platformDetails[0]['jilo_database'], $platform_id);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
|
||||
//
|
||||
|
@ -14,8 +16,8 @@ $db = connectDB($config, 'jilo', $platformDetails[0]['jilo_database'], $platform
|
|||
|
||||
////
|
||||
// monthly usage
|
||||
$conferenceObject = new Conference($db);
|
||||
$participantObject = new Participant($db);
|
||||
$conference = new Conference($db);
|
||||
$participant = new Participant($db);
|
||||
|
||||
// monthly conferences for the last year
|
||||
$fromMonth = (new DateTime())->sub(new DateInterval('P1Y'));
|
||||
|
@ -36,8 +38,8 @@ while ($fromMonth < $thisMonth) {
|
|||
$from_time = $fromMonth->format('Y-m-d');
|
||||
$until_time = $untilMonth->format('Y-m-d');
|
||||
|
||||
$searchConferenceNumber = $conferenceObject->conferenceNumber($from_time, $until_time);
|
||||
$searchParticipantNumber = $participantObject->participantNumber($from_time, $until_time);
|
||||
$searchConferenceNumber = $conference->conferenceNumber($from_time, $until_time);
|
||||
$searchParticipantNumber = $participant->participantNumber($from_time, $until_time);
|
||||
|
||||
// pretty format for displaying the month in the widget
|
||||
$month = $fromMonth->format('F Y');
|
||||
|
@ -69,15 +71,14 @@ $widget['filter'] = false;
|
|||
if (!empty($searchConferenceNumber) && !empty($searchParticipantNumber)) {
|
||||
$widget['full'] = true;
|
||||
}
|
||||
$widget['pagination'] = false;
|
||||
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/widget-monthly.php';
|
||||
include('../app/templates/widget-monthly.php');
|
||||
|
||||
|
||||
////
|
||||
// conferences in last 2 days
|
||||
$conference = new Conference($db);
|
||||
|
||||
// time range limit
|
||||
$from_time = date('Y-m-d', time() - 60 * 60 * 24 * 2);
|
||||
|
@ -85,7 +86,7 @@ $until_time = date('Y-m-d', time());
|
|||
$time_range_specified = true;
|
||||
|
||||
// prepare the result
|
||||
$search = $conferenceObject->conferencesAllFormatted($from_time, $until_time);
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
|
@ -129,14 +130,14 @@ if (!empty($conferences['records'])) {
|
|||
$widget['table_headers'] = array_keys($conferences['records'][0]);
|
||||
$widget['table_records'] = $conferences['records'];
|
||||
}
|
||||
$widget['pagination'] = false;
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/widget.php';
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
|
||||
////
|
||||
// last 10 conferences
|
||||
$conference = new Conference($db);
|
||||
|
||||
// all time
|
||||
$from_time = '0000-01-01';
|
||||
|
@ -146,7 +147,7 @@ $time_range_specified = false;
|
|||
$conference_number = 10;
|
||||
|
||||
// prepare the result
|
||||
$search = $conferenceObject->conferencesAllFormatted($from_time, $until_time);
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
|
@ -190,7 +191,6 @@ $widget['title'] = 'The last ' . $conference_number . ' conferences';
|
|||
$widget['collapsible'] = true;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = false;
|
||||
$widget['pagination'] = false;
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
$widget['full'] = true;
|
||||
|
@ -199,6 +199,6 @@ if (!empty($conferences['records'])) {
|
|||
}
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/widget.php';
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
// FIXME example data
|
||||
$one = date('Y-m-d',strtotime("-5 days"));
|
||||
$two = date('Y-m-d',strtotime("-4 days"));
|
||||
$three = date('Y-m-d',strtotime("-2 days"));
|
||||
$four = date('Y-m-d',strtotime("-1 days"));
|
||||
|
||||
$graph[0]['data0'] = [
|
||||
['date' => $one, 'value' => 10],
|
||||
['date' => $two, 'value' => 20],
|
||||
['date' => $three, 'value' => 15],
|
||||
['date' => $four, 'value' => 25],
|
||||
];
|
||||
|
||||
$graph[0]['data1'] = [
|
||||
['date' => $one, 'value' => 12],
|
||||
['date' => $two, 'value' => 23],
|
||||
['date' => $three, 'value' => 11],
|
||||
['date' => $four, 'value' => 27],
|
||||
];
|
||||
|
||||
$graph[0]['graph_name'] = 'conferences';
|
||||
$graph[0]['graph_title'] = 'Conferences in "' . htmlspecialchars($platformDetails[0]['name']) . '" over time';
|
||||
$graph[0]['graph_data0_label'] = 'Conferences from Jitsi logs (Jilo)';
|
||||
$graph[0]['graph_data1_label'] = 'Conferences from Jitsi API (Jilo Agents)';
|
||||
|
||||
$graph[1]['data0'] = [
|
||||
['date' => $one, 'value' => 20],
|
||||
['date' => $two, 'value' => 30],
|
||||
['date' => $three, 'value' => 15],
|
||||
['date' => $four, 'value' => 55],
|
||||
];
|
||||
|
||||
$graph[1]['data1'] = [
|
||||
['date' => $one, 'value' => 22],
|
||||
['date' => $two, 'value' => 33],
|
||||
['date' => $three, 'value' => 11],
|
||||
['date' => $four, 'value' => 57],
|
||||
];
|
||||
|
||||
$graph[1]['graph_name'] = 'participants';
|
||||
$graph[1]['graph_title'] = 'Participants in "' . htmlspecialchars($platformDetails[0]['name']) . '" over time';
|
||||
$graph[1]['graph_data0_label'] = 'Participants from Jitsi logs (Jilo)';
|
||||
$graph[1]['graph_data1_label'] = 'Participants from Jitsi API (Jilo Agents)';
|
||||
|
||||
include '../app/templates/graphs-combined.php';
|
||||
|
||||
?>
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../app/templates/help-main.php';
|
||||
|
||||
?>
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
require '../app/classes/agent.php';
|
||||
|
||||
$agentObject = new Agent($dbWeb);
|
||||
|
||||
$latestJvbConferences = $agentObject->getLatestData($platform_id, 'jvb', 'conferences');
|
||||
$latestJvbParticipants = $agentObject->getLatestData($platform_id, 'jvb', 'participants');
|
||||
$latestJicofoConferences = $agentObject->getLatestData($platform_id, 'jicofo', 'conferences');
|
||||
$latestJicofoParticipants = $agentObject->getLatestData($platform_id, 'jicofo', 'participants');
|
||||
|
||||
$widget['records'] = array();
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'LatestData';
|
||||
$widget['title'] = 'Latest data from Jilo Agents';
|
||||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = false;
|
||||
if (!empty($latestJvbConferences) && !empty($latestJvbParticipants) && !empty($latestJicofoConferences) && !empty($latestJicofoParticipants)) {
|
||||
$widget['full'] = true;
|
||||
}
|
||||
$widget['pagination'] = true;
|
||||
|
||||
|
||||
include '../app/templates/latest-data.php';
|
||||
|
||||
?>
|
|
@ -1,19 +1,25 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/user.php';
|
||||
|
||||
// clear the global error var before login
|
||||
unset($error);
|
||||
|
||||
try {
|
||||
|
||||
// connect to database
|
||||
$dbWeb = connectDB($config);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config);
|
||||
|
||||
$user = new User($db);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
|
||||
// login successful
|
||||
if ( $userObject->login($username, $password) ) {
|
||||
if ( $user->login($username, $password) ) {
|
||||
// if remember_me is checked, max out the session
|
||||
if (isset($_POST['remember_me'])) {
|
||||
// 30*24*60*60 = 30 days
|
||||
|
@ -40,17 +46,13 @@ try {
|
|||
|
||||
// redirect to index
|
||||
$_SESSION['notice'] = "Login successful";
|
||||
$user_id = $userObject->getUserId($username)[0]['id'];
|
||||
$logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user');
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
|
||||
// login failed
|
||||
} else {
|
||||
$_SESSION['error'] = "Login failed.";
|
||||
$user_id = $userObject->getUserId($username)[0]['id'];
|
||||
$logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP", 'user');
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
//
|
||||
// logs listings
|
||||
//
|
||||
|
||||
// specify time range
|
||||
include '../app/helpers/time_range.php';
|
||||
|
||||
// pagination variables
|
||||
$items_per_page = 15;
|
||||
$browse_page = $_REQUEST['p'] ?? 1;
|
||||
$browse_page = (int)$browse_page;
|
||||
$offset = ($browse_page -1) * $items_per_page;
|
||||
|
||||
// user or system
|
||||
$scope = 'user';
|
||||
|
||||
// prepare the result
|
||||
$search = $logObject->readLog($user_id, $scope, $offset, $items_per_page);
|
||||
$search_all = $logObject->readLog($user_id, $scope);
|
||||
|
||||
if (!empty($search)) {
|
||||
// we get total items and number of pages
|
||||
$item_count = count($search_all);
|
||||
$page_count = ceil($item_count / $items_per_page);
|
||||
|
||||
$logs = array();
|
||||
$logs['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
|
||||
// when we show only user's logs, omit user_id column
|
||||
if ($scope === 'user') {
|
||||
$log_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $item['time'],
|
||||
'log message' => $item['message']
|
||||
);
|
||||
} else {
|
||||
$log_record = array(
|
||||
// assign title to the field in the array record
|
||||
'userID' => $item['user_id'],
|
||||
'time' => $item['time'],
|
||||
'log message' => $item['message']
|
||||
);
|
||||
}
|
||||
|
||||
// populate the result array
|
||||
array_push($logs['records'], $log_record);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['collapsible'] = false;
|
||||
$widget['name'] = 'Logs';
|
||||
$username = $userObject->getUserDetails($user_id)[0]['username'];
|
||||
$widget['title'] = "Log events for user \"$username\"";
|
||||
$widget['filter'] = true;
|
||||
if (!empty($logs['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($logs['records'][0]);
|
||||
$widget['table_records'] = $logs['records'];
|
||||
}
|
||||
$widget['pagination'] = true;
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/logs-list.php';
|
||||
|
||||
?>
|
|
@ -1,9 +1,11 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/participant.php';
|
||||
|
||||
// connect to database
|
||||
$db = connectDB($config, 'jilo', $platformDetails[0]['jilo_database'], $platform_id);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
// specify time range
|
||||
include '../app/helpers/time_range.php';
|
||||
|
@ -32,38 +34,24 @@ if (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
|||
// Participant listings
|
||||
//
|
||||
|
||||
$participantObject = new Participant($db);
|
||||
|
||||
// pagination variables
|
||||
$items_per_page = 15;
|
||||
$browse_page = $_REQUEST['p'] ?? 1;
|
||||
$browse_page = (int)$browse_page;
|
||||
$offset = ($browse_page -1) * $items_per_page;
|
||||
$participant = new Participant($db);
|
||||
|
||||
// search and list specific participant ID
|
||||
if (isset($participantId)) {
|
||||
$search = $participantObject->conferenceByParticipantId($participantId, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $participantObject->conferenceByParticipantId($participantId, $from_time, $until_time);
|
||||
$search = $participant->conferenceByParticipantId($participantId, $from_time, $until_time, $participantId, $from_time, $until_time);
|
||||
// search and list specific participant name (stats_id)
|
||||
} elseif (isset($participantName)) {
|
||||
$search = $participantObject->conferenceByParticipantName($participantName, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $participantObject->conferenceByParticipantName($participantName, $from_time, $until_time);
|
||||
$search = $participant->conferenceByParticipantName($participantName, $from_time, $until_time);
|
||||
// search and list specific participant IP
|
||||
} elseif (isset($participantIp)) {
|
||||
$search = $participantObject->conferenceByParticipantIP($participantIp, $from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $participantObject->conferenceByParticipantIP($participantIp, $from_time, $until_time);
|
||||
$search = $participant->conferenceByParticipantIP($participantIp, $from_time, $until_time);
|
||||
// list of all participants (default)
|
||||
} else {
|
||||
// prepare the result
|
||||
$search = $participantObject->participantsAll($from_time, $until_time, $offset, $items_per_page);
|
||||
$search_all = $participantObject->participantsAll($from_time, $until_time);
|
||||
$search = $participant->participantsAll($from_time, $until_time);
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
// we get total items and number of pages
|
||||
$item_count = count($search_all);
|
||||
$page_count = ceil($item_count / $items_per_page);
|
||||
|
||||
$participants = array();
|
||||
$participants['records'] = array();
|
||||
|
||||
|
@ -130,7 +118,6 @@ $widget['name'] = 'Participants';
|
|||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
$widget['pagination'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
|
@ -150,6 +137,6 @@ if (!empty($participants['records'])) {
|
|||
}
|
||||
|
||||
// display the widget
|
||||
include '../app/templates/widget.php';
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,84 +1,5 @@
|
|||
<?php
|
||||
|
||||
$action = $_REQUEST['action'] ?? '';
|
||||
|
||||
// if a form is submitted, it's from the edit page
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
$item = $_REQUEST['item'] ?? '';
|
||||
|
||||
// avatar removal
|
||||
if ($item === 'avatar' && $action === 'remove') {
|
||||
$result = $userObject->removeAvatar($user_id, $config['avatars_path'].$userDetails[0]['avatar']);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] .= "Avatar for user \"{$userDetails[0]['username']}\" is removed. ";
|
||||
} else {
|
||||
$_SESSION['error'] .= "Removing the avatar failed. Error: $result ";
|
||||
}
|
||||
|
||||
header("Location: $app_root?page=profile");
|
||||
exit();
|
||||
}
|
||||
|
||||
// update the profile
|
||||
$updatedUser = [
|
||||
'name' => $_POST['name'] ?? '',
|
||||
'email' => $_POST['email'] ?? '',
|
||||
'timezone' => $_POST['timezone'] ?? '',
|
||||
'bio' => $_POST['bio'] ?? '',
|
||||
];
|
||||
$result = $userObject->editUser($user_id, $updatedUser);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] .= "User details for \"{$updatedUser['name']}\" are edited. ";
|
||||
} else {
|
||||
$_SESSION['error'] .= "Editing the user details failed. Error: $result ";
|
||||
}
|
||||
|
||||
// update the rights
|
||||
$newRights = $_POST['rights'] ?? array();
|
||||
// extract the new right_ids
|
||||
$userRightsIds = array_column($userRights, 'right_id');
|
||||
// what rights we need to add
|
||||
$rightsToAdd = array_diff($newRights, $userRightsIds);
|
||||
if (!empty($rightsToAdd)) {
|
||||
foreach ($rightsToAdd as $rightId) {
|
||||
$userObject->addUserRight($user_id, $rightId);
|
||||
}
|
||||
}
|
||||
// what rights we need to remove
|
||||
$rightsToRemove = array_diff($userRightsIds, $newRights);
|
||||
if (!empty($rightsToRemove)) {
|
||||
foreach ($rightsToRemove as $rightId) {
|
||||
$userObject->removeUserRight($user_id, $rightId);
|
||||
}
|
||||
}
|
||||
|
||||
// update the avatar
|
||||
if (!empty($_FILES['avatar_file']['tmp_name'])) {
|
||||
$result = $userObject->changeAvatar($user_id, $_FILES['avatar_file'], $config['avatars_path']);
|
||||
}
|
||||
|
||||
header("Location: $app_root?page=profile");
|
||||
exit();
|
||||
|
||||
// no form submitted, show the templates
|
||||
} else {
|
||||
$avatar = !empty($userDetails[0]['avatar']) ? $config['avatars_path'] . $userDetails[0]['avatar'] : $config['default_avatar'];
|
||||
$default_avatar = empty($userDetails[0]['avatar']) ? true : false;
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'edit':
|
||||
$allRights = $userObject->getAllRights();
|
||||
$allTimezones = timezone_identifiers_list();
|
||||
// if timezone is already set, we pass a flag for JS to not autodetect browser timezone
|
||||
$isTimezoneSet = !empty($userDetails[0]['timezone']);
|
||||
include '../app/templates/profile-edit.php';
|
||||
break;
|
||||
|
||||
default:
|
||||
include '../app/templates/profile.php';
|
||||
}
|
||||
}
|
||||
include('../app/templates/widget-profile.php');
|
||||
|
||||
?>
|
||||
|
|
|
@ -3,37 +3,36 @@
|
|||
// registration is allowed, go on
|
||||
if ($config['registration_enabled'] === true) {
|
||||
|
||||
// require '../app/classes/user.php';
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/user.php';
|
||||
unset($error);
|
||||
|
||||
try {
|
||||
|
||||
// connect to database
|
||||
$dbWeb = connectDB($config);
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config);
|
||||
|
||||
// $userObject = new User($dbWeb);
|
||||
$user = new User($db);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
|
||||
// registering
|
||||
$result = $userObject->register($username, $password);
|
||||
|
||||
// redirect to login
|
||||
if ($result === true) {
|
||||
if ( $user->register($username, $password) ) {
|
||||
$_SESSION['notice'] = "Registration successful.<br />You can log in now.";
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
// registration fail, redirect to login
|
||||
} else {
|
||||
$_SESSION['error'] = "Registration failed. $result";
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
$_SESSION['error'] = "Registration failed.";
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
$error = getError('There was an unexpected error. Please try again.', $e->getMessage());
|
||||
}
|
||||
|
||||
include '../app/templates/block-message.php';
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Jilo components status checks
|
||||
//
|
||||
|
||||
require '../app/classes/agent.php';
|
||||
$agentObject = new Agent($dbWeb);
|
||||
|
||||
include '../app/templates/status-server.php';
|
||||
|
||||
foreach ($platformsAll as $platform) {
|
||||
|
||||
include '../app/templates/status-platform.php';
|
||||
|
||||
$agentDetails = $agentObject->getAgentDetails($platform['id']);
|
||||
foreach ($agentDetails as $agent) {
|
||||
$agent_url = parse_url($agent['url']);
|
||||
$agent_protocol = isset($agent_url['scheme']) ? $agent_url['scheme']: '';
|
||||
$agent_host = isset($agent_url['host']) ? $agent_url['host']: '';
|
||||
$agent_port = isset($agent_url['port']) ? $agent_url['port']: '';
|
||||
|
||||
// we get agent data to check availability
|
||||
$agent_response = $agentObject->fetchAgent($agent['id'], true);
|
||||
$agent_data = json_decode($agent_response);
|
||||
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$agent_availability = '<span class="text-warning">unknown</span>';
|
||||
foreach ($agent_data as $key => $value) {
|
||||
if ($key === 'error') {
|
||||
$agent_availability = '<span class="text-danger">' . htmlspecialchars($value) . '</span>';
|
||||
break;
|
||||
}
|
||||
if (preg_match('/_state$/', $key)) {
|
||||
if ($value === 'error') {
|
||||
$agent_availability = '<span class="text-danger">not running</span>';
|
||||
break;
|
||||
}
|
||||
if ($value === 'running') {
|
||||
$agent_availability = '<span class="text-success">running</span>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$agent_availability = 'json error';
|
||||
}
|
||||
|
||||
include '../app/templates/status-agent.php';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
<!-- jilo agents -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<p class="h4 card-header">Jilo Agents on platform <?= htmlspecialchars($platform_id) ?> (<?= htmlspecialchars($platformDetails[0]['name']) ?>)</p>
|
||||
<div class="card-body">
|
||||
<?php foreach ($agentDetails as $agent) { ?>
|
||||
<p class="card-text text-left" style="text-align: left;">
|
||||
agent id: <strong><?= htmlspecialchars($agent['id']) ?></strong>
|
||||
agent type: <?= htmlspecialchars($agent['agent_type_id']) ?> (<strong><?= htmlspecialchars($agent['agent_description']) ?></strong>)
|
||||
<br />
|
||||
endpoint: <strong><?= htmlspecialchars($agent['url']) ?><?= htmlspecialchars($agent['agent_endpoint']) ?></strong>
|
||||
<br />
|
||||
<?php
|
||||
$payload = [
|
||||
'iss' => 'Jilo Web',
|
||||
'aud' => $config['domain'],
|
||||
'iat' => time(),
|
||||
'exp' => time() + 3600,
|
||||
'agent_id' => $agent['id']
|
||||
];
|
||||
$jwt = $agentObject->generateAgentToken($payload, $agent['secret_key']);
|
||||
// print_r($_SESSION);
|
||||
?>
|
||||
<?php if (isset($_SESSION["agent{$agent['id']}_cache"])) { ?>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-status" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get the agent status" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '/status', '<?= htmlspecialchars($jwt) ?>', true)">get status</button>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-fetch" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get data from the agent" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '<?= htmlspecialchars($agent['agent_endpoint']) ?>', '<?= htmlspecialchars($jwt) ?>', true)">fetch data</button>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-cache" class="btn btn-secondary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="load cache" onclick="loadCache('<?= htmlspecialchars($agent['id']) ?>')">load cache</button>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-clear" class="btn btn-danger" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="clear cache" onclick="clearCache('<?= htmlspecialchars($agent['id']) ?>')">clear cache</button>
|
||||
<span id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" style="margin: 5px 0;"></span>
|
||||
<?php } else { ?>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-status" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get the agent status" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '/status', '<?= htmlspecialchars($jwt) ?>', true)">get status</button>
|
||||
<button id="agent<?= htmlspecialchars($agent['id']) ?>-fetch" class="btn btn-primary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="get data from the agent" onclick="fetchData('<?= htmlspecialchars($agent['id']) ?>', '<?= htmlspecialchars($agent['url']) ?>', '<?= htmlspecialchars($agent['agent_endpoint']) ?>', '<?= htmlspecialchars($jwt) ?>')">fetch data</button>
|
||||
<button style="display: none" disabled id="agent<?= htmlspecialchars($agent['id']) ?>-cache" class="btn btn-secondary" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="load cache" onclick="loadCache('<?= htmlspecialchars($agent['id']) ?>')">load cache</button>
|
||||
<button style="display: none" disabled id="agent<?= htmlspecialchars($agent['id']) ?>-clear" class="btn btn-danger" data-toggle="tooltip" data-trigger="hover" data-placement="bottom" title="clear cache" onclick="clearCache('<?= htmlspecialchars($agent['id']) ?>')">clear cache</button>
|
||||
<span style="display: none" id="cacheInfo<?= htmlspecialchars($agent['id']) ?>" style="margin: 5px 0;"></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<pre class="results" id="result<?= htmlspecialchars($agent['id']) ?>">click a button to display data from the agent.</pre>
|
||||
<?php } ?>
|
|
@ -1,7 +1,7 @@
|
|||
<?php if (isset($error)) { ?>
|
||||
<div class="error"><?= $error ?></div>
|
||||
<div class="error"><?php echo $error; ?></div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (isset($notice)) { ?>
|
||||
<div class="notice"><?= $notice ?></div>
|
||||
<div class="notice"><?php echo $notice; ?></div>
|
||||
<?php } ?>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
<!-- Results filter -->
|
||||
<div class="card w-auto bg-light border-light card-body text-right" style="text-align: right;">
|
||||
<form method="POST" id="filter_form" class="filter-results" action="?platform=<?= htmlspecialchars($platform_id) ?>&page=<?= htmlspecialchars($page) ?>">
|
||||
<form method="POST" id="filter_form" action="?platform=<?= $platform_id?>&page=<?= $page ?>">
|
||||
<label for="from_time">from</label>
|
||||
<input type="date" id="from_time" name="from_time"<?php if (isset($_REQUEST['from_time'])) echo " value=\"" . htmlspecialchars($from_time) . "\"" ?> />
|
||||
<input type="date" id="from_time" name="from_time"<?php if (isset($_REQUEST['from_time'])) echo " value=\"" . $_REQUEST['from_time'] . "\"" ?> />
|
||||
<label for="until_time">until</label>
|
||||
<input type="date" id="until_time" name="until_time"<?php if (isset($_REQUEST['until_time'])) echo " value=\"" . htmlspecialchars($until_time) . "\"" ?> />
|
||||
<input type="text" name="id" placeholder="ID"<?php if (isset($_REQUEST['id'])) echo " value=\"" . htmlspecialchars($_REQUEST['id']) . "\"" ?> />
|
||||
<input type="text" name="name" placeholder="name"<?php if (isset($_REQUEST['name'])) echo " value=\"" . htmlspecialchars($_REQUEST['name']) . "\"" ?> />
|
||||
<input type="date" id="until_time" name="until_time"<?php if (isset($_REQUEST['until_time'])) echo " value=\"" . $_REQUEST['until_time'] . "\"" ?> />
|
||||
<input type="text" name="id" placeholder="ID"<?php if (isset($_REQUEST['id'])) echo " value=\"" . $_REQUEST['id'] . "\"" ?> />
|
||||
<input type="text" name="name" placeholder="name"<?php if (isset($_REQUEST['name'])) echo " value=\"" . $_REQUEST['name'] . "\"" ?> />
|
||||
<?php if ($page == 'participants') { ?>
|
||||
<input type="text" name="ip" placeholder="ip address"<?php if (isset($_REQUEST['ip'])) echo " value=\"" . htmlspecialchars($_REQUEST['ip']) . "\"" ?> maxlength="15" size="15" />
|
||||
<input type="text" name="ip" placeholder="ip address"<?php if (isset($_REQUEST['ip'])) echo " value=\"" . $_REQUEST['ip'] . "\"" ?> maxlength="15" size="15" />
|
||||
<?php } ?>
|
||||
<input type="button" onclick="clearFilter()" value="clear" />
|
||||
<input type="submit" value="search" />
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
|
||||
<!-- widget "agents" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<p class="h4 card-header">Add new Jilo Agent to Jitsi platform "<strong><?= htmlspecialchars($platformDetails[0]['name']) ?></strong>"</p>
|
||||
<div class="card-body">
|
||||
<!--p class="card-text">add new agent:</p-->
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="type" class="form-label">type</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" type="text" name="type" id="agent_type_id" required>
|
||||
<option></option>
|
||||
<?php foreach ($jilo_agent_types as $agent_type) { ?>
|
||||
<option value="<?= htmlspecialchars($agent_type['id']) ?>"<?php
|
||||
if (in_array($agent_type['id'], $jilo_agent_types_in_platform)) {
|
||||
echo 'disabled="disabled"';
|
||||
} ?>>
|
||||
<?= htmlspecialchars($agent_type['description']) ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<p class="text-start"><small>type of agent (meet, jvb, jibri, etc.)<br />if a type has already been aded, it's disabled here</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="url" class="form-label">URL</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="url" value="https://" required />
|
||||
<p class="text-start"><small>URL of the Jilo Agent API (https://example.com:8081)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="secret_key" class="form-label">secret key</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="secret_key" value="" required />
|
||||
<p class="text-start"><small>secret key for generating the access JWT token</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="check_period" class="form-label">check period</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="check_period" value="0" required />
|
||||
<p class="text-start"><small>period in minutes for the automatic agent check (0 disables it)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="new" value="true" />
|
||||
<input type="hidden" name="item" value="agent" />
|
||||
|
||||
<br />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "agents" -->
|
|
@ -4,7 +4,7 @@
|
|||
<p class="h4 card-header">Add new Jitsi platform</p>
|
||||
<div class="card-body">
|
||||
<!--p class="card-text">add new platform:</p-->
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<form method="POST" action="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
|
@ -12,7 +12,7 @@
|
|||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="name" value="" required autofocus />
|
||||
<input class="form-control" type="text" name="name" value="" required />
|
||||
<p class="text-start"><small>descriptive name for the platform</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<input type="hidden" name="new" value="true" />
|
||||
|
||||
<br />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config" />Cancel</a>
|
||||
<a class="btn btn-secondary" href="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
|
||||
<!-- widget "agents" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<p class="h4 card-header">Jilo Agent configuration for Jitsi platform <strong>"<?= htmlspecialchars($platformDetails[0]['name']) ?>"</strong></p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">delete an agent:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<?php
|
||||
foreach ($agentDetails[0] as $key => $value) {
|
||||
// if ($key === 'id') continue;
|
||||
?>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="<?= htmlspecialchars($key) ?>" class="form-label"><?= htmlspecialchars($key) ?>:</label>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="text-start"><?= htmlspecialchars($value ?? '') ?></div>
|
||||
<input type="hidden" name="<?= htmlspecialchars($key) ?>" value="<?= htmlspecialchars($value ?? '') ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<br />
|
||||
<input type="hidden" name="agent" value="<?= htmlspecialchars($agentDetails[0]['id']) ?>" />
|
||||
<input type="hidden" name="delete" value="true" />
|
||||
<p class="h5 text-danger">Are you sure you want to delete this agent?</p>
|
||||
<br />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform_id) ?>agent<?= htmlspecialchars($agentDetails[0]['id']) ?>" />Cancel</a>
|
||||
<input type="submit" class="btn btn-danger" value="Delete" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "agents" -->
|
|
@ -1,21 +1,18 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<p class="h4 card-header">Jilo web configuration for Jitsi platform <strong>"<?= htmlspecialchars($platformDetails[0]['name']) ?>"</strong></p>
|
||||
<p class="h4 card-header">Jilo web configuration for Jitsi platform "<?= htmlspecialchars($platform_id) ?>"</p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">delete a platform:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<?php
|
||||
foreach ($platformDetails[0] as $key => $value) {
|
||||
if ($key === 'id') continue;
|
||||
?>
|
||||
<form method="POST" action="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<?php foreach ($config['platforms'][$platform_id] as $config_item => $config_value) { ?>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="<?= htmlspecialchars($key) ?>" class="form-label"><?= htmlspecialchars($key) ?>:</label>
|
||||
<label for="<?= htmlspecialchars($config_item) ?>" class="form-label"><?= htmlspecialchars($config_item) ?>:</label>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="text-start"><?= htmlspecialchars($value) ?? '' ?></div>
|
||||
<input type="hidden" name="<?= htmlspecialchars($key) ?>" value="<?= htmlspecialchars($value ?? '')?>" />
|
||||
<div class="text-start"><?= htmlspecialchars($config_value ?? '')?></div>
|
||||
<input type="hidden" name="<?= htmlspecialchars($config_item) ?>" value="<?= htmlspecialchars($config_value ?? '')?>" />
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
@ -24,7 +21,7 @@ foreach ($platformDetails[0] as $key => $value) {
|
|||
<input type="hidden" name="delete" value="true" />
|
||||
<p class="h5 text-danger">Are you sure you want to delete this platform?</p>
|
||||
<br />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform_id) ?>" />Cancel</a>
|
||||
<a class="btn btn-secondary" href="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-danger" value="Delete" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
|
||||
<!-- agents -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<p class="h4 card-header">Jilo Agent configuration for Jitsi platform <strong>"<?= htmlspecialchars($platformDetails[0]['name']) ?>"</strong></p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">edit the agent details:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="type_id" class="form-label">type</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" type="text" name="type" id="agent_type_id" required>
|
||||
<option></option>
|
||||
<?php foreach ($jilo_agent_types as $agent_type) { ?>
|
||||
<option value="<?= htmlspecialchars($agent_type['id']) ?>" <?php if ($agentDetails[0]['agent_type_id'] === $agent_type['id']) echo 'selected'; ?>>
|
||||
<?= htmlspecialchars($agent_type['description']) ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<p class="text-start"><small>type of agent (meet, jvb, jibri, all)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="url" class="form-label">URL</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="url" value="<?= htmlspecialchars($agentDetails[0]['url']) ?>" required />
|
||||
<p class="text-start"><small>URL of the Jilo Agent API (https://example.com:8081)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="secret_key" class="form-label">secret key</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="secret_key" value="<?= htmlspecialchars($agentDetails[0]['secret_key']) ?>" required />
|
||||
<p class="text-start"><small>secret key for generating the access JWT token</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="check_period" class="form-label">check period</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="check_period" value="<?= htmlspecialchars($agentDetails[0]['check_period']) ?>" required />
|
||||
<p class="text-start"><small>period in minutes for the automatic agent check (0 disables it)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<br />
|
||||
<input type="hidden" name="agent" value="<?= htmlspecialchars($agentDetails[0]['id']) ?>" />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform_id) ?>agent<?= htmlspecialchars($agentDetails[0]['id']) ?>" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /agents -->
|
|
@ -1,26 +1,23 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<p class="h4 card-header">Jilo web configuration for Jitsi platform <strong>"<?= htmlspecialchars($platformDetails[0]['name']) ?>"</strong></p>
|
||||
<p class="h4 card-header">Jilo web configuration for Jitsi platform "<?= htmlspecialchars($platform_id) ?>"</p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">edit the platform details:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<?php
|
||||
foreach ($platformDetails[0] as $key => $value) {
|
||||
if ($key === 'id') continue;
|
||||
?>
|
||||
<form method="POST" action="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
<?php foreach ($config['platforms'][$platform_id] as $config_item => $config_value) { ?>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="<?= htmlspecialchars($config_item) ?>" class="form-label"><?= htmlspecialchars($key) ?></label>
|
||||
<label for="<?= htmlspecialchars($config_item) ?>" class="form-label"><?= htmlspecialchars($config_item) ?></label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="<?= htmlspecialchars($key) ?>" value="<?= htmlspecialchars($value ?? '') ?>" required autofocus />
|
||||
<?php if ($key === 'name') { ?>
|
||||
<input class="form-control" type="text" name="<?= htmlspecialchars($config_item) ?>" value="<?= htmlspecialchars($config_value ?? '')?>" required />
|
||||
<?php if ($config_item === 'name') { ?>
|
||||
<p class="text-start"><small>descriptive name for the platform</small></p>
|
||||
<?php } elseif ($key === 'jitsi_url') { ?>
|
||||
<?php } elseif ($config_item === 'jitsi_url') { ?>
|
||||
<p class="text-start"><small>URL of the Jitsi Meet (used for checks and for loading config.js)</small></p>
|
||||
<?php } elseif ($key === 'jilo_database') { ?>
|
||||
<?php } elseif ($config_item === 'jilo_database') { ?>
|
||||
<p class="text-start"><small>path to the database file (relative to the app root)</small></p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
@ -28,7 +25,7 @@ foreach ($platformDetails[0] as $key => $value) {
|
|||
<?php } ?>
|
||||
<br />
|
||||
<input type="hidden" name="platform" value="<?= htmlspecialchars($platform_id) ?>" />
|
||||
<a class="btn btn-secondary" href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform_id) ?>" />Cancel</a>
|
||||
<a class="btn btn-secondary" href="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<p class="h4 card-header">Configuration of the Jitsi platform <strong><?= htmlspecialchars($platformDetails[0]['name']) ?></strong></p>
|
||||
<p class="h4 card-header">Configuration of the Jitsi platform <strong><?= htmlspecialchars($platformDetails['name']) ?></strong></p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">
|
||||
<span class="m-3">URL: <?= htmlspecialchars($platformDetails[0]['jitsi_url']) ?></span>
|
||||
<span class="m-3">URL: <?= htmlspecialchars($platformDetails['jitsi_url']) ?></span>
|
||||
<span class="m-3">FILE: config.js</span>
|
||||
<?php if ($mode === 'raw') { ?>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs">view only active lines</a></span>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs">view only active lines</a></span>
|
||||
<?php } else { ?>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs&mode=raw">view raw file contents</a></span>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs&mode=raw">view raw file contents</a></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<pre class="results">
|
||||
<pre style="text-align: left;">
|
||||
<?php
|
||||
echo htmlspecialchars($platformConfigjs);
|
||||
?>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<p class="h4 card-header">Configuration of the Jitsi platform <strong><?= htmlspecialchars($platformDetails[0]['name']) ?></strong></p>
|
||||
<p class="h4 card-header">Configuration of the Jitsi platform <strong><?= htmlspecialchars($platformDetails['name']) ?></strong></p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">
|
||||
<span class="m-3">URL: <?= htmlspecialchars($platformDetails[0]['jitsi_url']) ?></span>
|
||||
<span class="m-3">URL: <?= htmlspecialchars($platformDetails['jitsi_url']) ?></span>
|
||||
<span class="m-3">FILE: interface_config.js</span>
|
||||
<?php if ($mode === 'raw') { ?>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs">view only active lines</a></span>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs">view only active lines</a></span>
|
||||
<?php } else { ?>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs&mode=raw">view raw file contents</a></span>
|
||||
<span class="m-3"><a class="btn btn-light" href="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs&mode=raw">view raw file contents</a></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<pre class="results">
|
||||
<pre style="text-align: left;">
|
||||
<?php
|
||||
echo htmlspecialchars($platformInterfaceConfigjs);
|
||||
?>
|
||||
|
|
|
@ -3,125 +3,12 @@
|
|||
<div class="card text-center w-75 mx-lef">
|
||||
<p class="h4 card-header">Jilo web configuration</p>
|
||||
<div class="card-body">
|
||||
<p class="card-text">main variables</p>
|
||||
<p class="card-text">platform variables</p>
|
||||
<?php
|
||||
include '../app/helpers/render.php';
|
||||
renderConfig($config, '0');
|
||||
echo "\n";
|
||||
?>
|
||||
|
||||
<hr />
|
||||
<p class="card-text">platforms configuration <a class="btn btn-secondary" style="padding: 0px;" href="<?= htmlspecialchars($app_root) ?>?page=config&item=platform&action=add">add new</a></p>
|
||||
|
||||
<?php foreach ($platformsAll as $platform_array) {
|
||||
$agents = $agentObject->getAgentDetails($platform_array['id']);
|
||||
?>
|
||||
|
||||
<a name="platform<?= htmlspecialchars($platform_array['id']) ?>"></a>
|
||||
<div class="row mb-3" style="padding-left: 0px;">
|
||||
<div class="border bg-light" style="padding-left: 50px; padding-bottom: 0px; padding-top: 0px;">
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapsePlatform<?= htmlspecialchars($platform_array['id']) ?>" role="button" aria-expanded="true" aria-controls="collapsePlatform<?= htmlspecialchars($platform_array['id']) ?>">
|
||||
<div class="border bg-white text-start mb-3 rounded mt-3" data-toggle="tooltip" data-placement="bottom" title="configuration for platform <?= htmlspecialchars($platform_array['id']) ?>">
|
||||
<i class="fas fa-wrench"></i>
|
||||
<small>platform <?= htmlspecialchars($platform_array['id']) ?> (<?= htmlspecialchars($platform_array['name']) ?>)</small>
|
||||
</div>
|
||||
</a>
|
||||
<div class="collapse show" id="collapsePlatform<?= htmlspecialchars($platform_array['id']) ?>">
|
||||
|
||||
<div class="row mb-1" style="padding-left: 0px;">
|
||||
<div class="col-md-8 text-start">
|
||||
|
||||
<div class="row mb-1">
|
||||
<div class="col-md-8 text-start">
|
||||
<a class="btn btn-secondary" style="padding: 2px;" href="<?= htmlspecialchars($app_root) ?>?page=config&platform=<?= htmlspecialchars($platform_array['id']) ?>&action=edit">edit platform</a>
|
||||
<?php if (count($platformsAll) <= 1) { ?>
|
||||
<span class="btn btn-light" style="padding: 2px;" href="#" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="can't delete the last platform">delete platform</span>
|
||||
<?php } else { ?>
|
||||
<a class="btn btn-danger" style="padding: 2px;" href="<?= htmlspecialchars($app_root) ?>?page=config&platform=<?= htmlspecialchars($platform_array['id']) ?>&action=delete">delete platform</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="padding-left: 100px; padding-bottom: 20px;">
|
||||
<?php foreach ($platform_array as $key => $value) {
|
||||
if ($key === 'id') continue;
|
||||
?>
|
||||
<div class="row mb-1" style="padding-left: 100px;">
|
||||
<div class="col-md-4 text-end">
|
||||
<?= htmlspecialchars($key) ?>:
|
||||
</div>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($value) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
<p class="card-text">jilo agents on platform <?= htmlspecialchars($platform_array['id']) ?> (<?= htmlspecialchars($platform_array['name']) ?>)
|
||||
<br />
|
||||
total <?= htmlspecialchars(count($agents)) ?> <?= htmlspecialchars(count($agents)) === 1 ? 'jilo agent' : 'jilo agents' ?>
|
||||
<a class="btn btn-secondary" style="padding: 0px;" href="<?= htmlspecialchars($app_root) ?>?page=config&platform=<?= htmlspecialchars($platform_array['id']) ?>&action=add-agent">
|
||||
add new
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<?php foreach ($agents as $agent_array) { ?>
|
||||
|
||||
<a name="platform<?= htmlspecialchars($platform_array['id']) ?>agent<?= htmlspecialchars($agent_array['id']) ?>"></a>
|
||||
<div class="row mb-3" style="padding-left: 0px;">
|
||||
<div class="border rounded bg-light" style="padding-left: 50px; padding-bottom: 20px; padding-top: 20px;">
|
||||
<div class="row mb-1" style="padding-left: 0px;">
|
||||
<div class="col-md-4 text-end">
|
||||
agent id <?= htmlspecialchars($agent_array['id']) ?>:
|
||||
</div>
|
||||
<div class="col-md-8 text-start">
|
||||
<a class="btn btn-secondary" style="padding: 2px;" href="<?= htmlspecialchars($app_root) ?>?page=config&platform=<?= htmlspecialchars($agent_array['platform_id']) ?>&agent=<?= htmlspecialchars($agent_array['id']) ?>&action=edit">edit agent</a>
|
||||
<a class="btn btn-danger" style="padding: 2px;" href="<?= htmlspecialchars($app_root) ?>?page=config&platform=<?= htmlspecialchars($agent_array['platform_id']) ?>&agent=<?= htmlspecialchars($agent_array['id']) ?>&action=delete">delete agent</a>
|
||||
</div>
|
||||
<div style="padding-left: 100px; padding-bottom: 20px;">
|
||||
<div class="row mb-1" style="padding-left: 100px;">
|
||||
<div class="col-md-4 text-end">
|
||||
agent type:
|
||||
</div>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($agent_array['agent_description']) ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1" style="padding-left: 100px;">
|
||||
<div class="col-md-4 text-end">
|
||||
endpoint:
|
||||
</div>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($agent_array['url'].$agent_array['agent_endpoint']) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (isset($agent_array['check_period']) && $agent_array['check_period'] !== 0) { ?>
|
||||
<div class="row mb-1" style="padding-left: 100px;">
|
||||
<div class="col-md-4 text-end">
|
||||
check period:
|
||||
</div>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($agent_array['check_period']) ?> <?= ($agent_array['check_period'] == 1 ? 'minute' : 'minutes') ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
<div class="text-center">
|
||||
<div class="mt-3 h5">The page is not found.</div>
|
||||
<div>
|
||||
<small>go to <a href="<?= htmlspecialchars($app_root) ?>">front page</a> or to <a href="<?= htmlspecialchars($app_root) ?>?page=profile">your profile</a></small>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
<div class="text-center">
|
||||
<div class="mt-3 h5">You have no access to this page.</div>
|
||||
<div>
|
||||
<small>go to <a href="<?= htmlspecialchars($app_root) ?>">front page</a> or to <a href="<?= htmlspecialchars($app_root) ?>?page=profile">your profile</a></small>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
|
||||
<!-- Results filter -->
|
||||
<div class="card w-auto bg-light border-light card-body text-right" style="text-align: right;">
|
||||
<form method="POST" id="filter_form" class="filter-results" action="?platform=<?= htmlspecialchars($platform_id) ?>&page=<?= htmlspecialchars($page) ?>">
|
||||
<label for="from_time">from</label>
|
||||
<input type="date" id="from_time" name="from_time"<?php if (isset($_REQUEST['from_time'])) echo " value=\"" . htmlspecialchars($from_time) . "\"" ?> />
|
||||
<label for="until_time">until</label>
|
||||
<input type="date" id="until_time" name="until_time"<?php if (isset($_REQUEST['until_time'])) echo " value=\"" . htmlspecialchars($until_time) . "\"" ?> />
|
||||
<input type="text" name="id" placeholder="component ID"<?php if (isset($_REQUEST['id'])) echo " value=\"" . htmlspecialchars($_REQUEST['id']) . "\"" ?> />
|
||||
<input type="text" name="name" placeholder="component name"<?php if (isset($_REQUEST['name'])) echo " value=\"" . htmlspecialchars($_REQUEST['name']) . "\"" ?> />
|
||||
<input type="text" name="event" placeholder="event name"<?php if (isset($_REQUEST['event'])) echo " value=\"" . htmlspecialchars($_REQUEST['event']) . "\"" ?> />
|
||||
<input type="button" onclick="clearFilter()" value="clear" />
|
||||
<input type="submit" value="search" />
|
||||
</form>
|
||||
<script>
|
||||
function clearFilter() {
|
||||
document.getElementById("filter_form").reset();
|
||||
const filterFields = document.querySelectorAll("#filter_form input");
|
||||
filterFields.forEach(input => {
|
||||
if (input.type === 'text' ||input.type === 'date') {
|
||||
input.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<!-- /Results filter -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<p class="m-3">time period: <strong><?= htmlspecialchars($from_time) ?> - <?= htmlspecialchars($until_time) ?></strong></p>
|
||||
<?php } ?>
|
||||
<div class="mb-5">
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<?php foreach ($widget['table_headers'] as $header) { ?>
|
||||
<th scope="col"><?= htmlspecialchars($header) ?></th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($widget['table_records'] as $row) { ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $key => $column) { ?>
|
||||
<?php if ($key === 'component ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=components&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'component') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=components&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } else { ?>
|
||||
<td><?= htmlspecialchars($column ?? '') ?></td>
|
||||
<?php }
|
||||
} ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
if ($widget['pagination'] && $item_count > $items_per_page) {
|
||||
$url = "$app_root?platform=$platform_id&page=$page";
|
||||
include '../app/helpers/pagination.php';
|
||||
}
|
||||
?>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
|
@ -1,94 +0,0 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
|
||||
<!-- Results filter -->
|
||||
<div class="card w-auto bg-light border-light card-body text-right" style="text-align: right;">
|
||||
<form method="POST" id="filter_form" class="filter-results" action="?platform=<?= htmlspecialchars($platform_id) ?>&page=<?= htmlspecialchars($page) ?>">
|
||||
<label for="from_time">from</label>
|
||||
<input type="date" id="from_time" name="from_time"<?php if (isset($_REQUEST['from_time'])) echo " value=\"" . htmlspecialchars($from_time) . "\"" ?> />
|
||||
<label for="until_time">until</label>
|
||||
<input type="date" id="until_time" name="until_time"<?php if (isset($_REQUEST['until_time'])) echo " value=\"" . htmlspecialchars($until_time) . "\"" ?> />
|
||||
<input type="text" name="id" placeholder="conference ID"<?php if (isset($_REQUEST['id'])) echo " value=\"" . htmlspecialchars($_REQUEST['id']) . "\"" ?> />
|
||||
<input type="text" name="name" placeholder="conference name"<?php if (isset($_REQUEST['name'])) echo " value=\"" . htmlspecialchars($_REQUEST['name']) . "\"" ?> />
|
||||
<input type="button" onclick="clearFilter()" value="clear" />
|
||||
<input type="submit" value="search" />
|
||||
</form>
|
||||
<script>
|
||||
function clearFilter() {
|
||||
document.getElementById("filter_form").reset();
|
||||
const filterFields = document.querySelectorAll("#filter_form input");
|
||||
filterFields.forEach(input => {
|
||||
if (input.type === 'text' ||input.type === 'date') {
|
||||
input.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<!-- /Results filter -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<p class="m-3">time period: <strong><?= htmlspecialchars($from_time) ?> - <?= htmlspecialchars($until_time) ?></strong></p>
|
||||
<?php } ?>
|
||||
<div class="mb-5">
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<?php foreach ($widget['table_headers'] as $header) { ?>
|
||||
<th scope="col"><?= htmlspecialchars($header) ?></th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($widget['table_records'] as $row) { ?>
|
||||
<tr>
|
||||
<?php $stats_id = false;
|
||||
$participant_ip = false;
|
||||
if (isset($row['event']) && $row['event'] === 'stats_id') $stats_id = true;
|
||||
if (isset($row['event']) && $row['event'] === 'pair selected') $participant_ip = true;
|
||||
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference ID' && isset($conferenceId) && $conferenceId === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($key === 'conference ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'conference name' && isset($conferenceName) && $conferenceName === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($key === 'conference name') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'participant ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($stats_id && $key === 'parameter') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($participant_ip && $key === 'parameter') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&ip=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php
|
||||
// in general listings we don't show seconds and miliseconds
|
||||
} elseif ($key === 'start' || $key === 'end') { ?>
|
||||
<td><?= htmlspecialchars(substr($column ?? '', 0, -7)) ?></td>
|
||||
<?php } else { ?>
|
||||
<td><?= htmlspecialchars($column ?? '') ?></td>
|
||||
<?php }
|
||||
} ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
if ($widget['pagination'] && $item_count > $items_per_page) {
|
||||
$url = "$app_root?platform=$platform_id&page=$page";
|
||||
include '../app/helpers/pagination.php';
|
||||
}
|
||||
?>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
|
@ -3,8 +3,8 @@
|
|||
<h2 class="card-header">Login</h2>
|
||||
<div class="card-body">
|
||||
<p class="card-text"><strong>Welcome to JILO!</strong><br />Please enter login credentials:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?page=login">
|
||||
<input type="text" name="username" placeholder="Username" required autofocus />
|
||||
<form method="POST" action="<?= $app_root ?>?page=login">
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<br />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<br />
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<h2 class="card-header">Register</h2>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Enter credentials for registration:</p>
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?page=register">
|
||||
<input type="text" name="username" placeholder="Username" required autofocus />
|
||||
<form method="POST" action="<?php= $app_root ?>?page=register">
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<br />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<br /> <br />
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
|
||||
<hr /><p class="m-3">NB: This functionality is still under development. The data is just an example.</p><hr /><!-- FIXME remove when implemented -->
|
||||
|
||||
<div class="row">
|
||||
<div class="card w-auto bg-light border-light card-body filter-results">
|
||||
<div class="btn-group" role="group">
|
||||
<input type="button" class="button" style="margin-right: 3px;" onclick="setTimeRange('today'); setActive(this)" value="today" />
|
||||
<input type="button" class="button" style="margin-right: 3px;" onclick="setTimeRange('last2days'); setActive(this)" value="last 2 days" />
|
||||
<input type="button" class="button active" style="margin-right: 3px;" onclick="setTimeRange('last7days'); setActive(this)" value="last 7 days" />
|
||||
<input type="button" class="button" style="margin-right: 3px;" onclick="setTimeRange('thisMonth'); setActive(this)" value="month" />
|
||||
<input type="button" class="button" style="margin-right: 18px;" onclick="setTimeRange('thisYear'); setActive(this)" value="year" />
|
||||
|
||||
<input type="date" style="margin-right: 3px;" id="start-date">
|
||||
|
||||
<input type="date" style="margin-right: 3px;" id="end-date">
|
||||
<input type="button" id="custom_range" class="button" onclick="setCustomTimeRange(); setActive(this)" value="custom range" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Define an array to store all graph instances
|
||||
var graphs = [];
|
||||
</script>
|
||||
|
||||
<?php
|
||||
|
||||
foreach ($graph as $data) {
|
||||
include '../app/helpers/graph.php';
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
// Function to update the label and propagate zoom across charts
|
||||
function propagateZoom(chart) {
|
||||
var startDate = chart.scales.x.min;
|
||||
var endDate = chart.scales.x.max;
|
||||
|
||||
// Update the datetime input fields
|
||||
document.getElementById('start-date').value = new Date(startDate).toISOString().slice(0, 10);
|
||||
document.getElementById('end-date').value = new Date(endDate).toISOString().slice(0, 10);
|
||||
|
||||
// Update all charts with the new date range
|
||||
graphs.forEach(function(graphObj) {
|
||||
if (graphObj.graph !== chart) {
|
||||
graphObj.graph.options.scales.x.min = startDate;
|
||||
graphObj.graph.options.scales.x.max = endDate;
|
||||
graphObj.graph.update(); // Redraw chart with new range
|
||||
}
|
||||
updatePeriodLabel(graphObj.graph, graphObj.label); // Update period label
|
||||
});
|
||||
}
|
||||
|
||||
// Predefined time range buttons
|
||||
function setTimeRange(range) {
|
||||
var startDate, endDate;
|
||||
var now = new Date();
|
||||
|
||||
switch (range) {
|
||||
case 'today':
|
||||
startDate = new Date(now.setHours(0, 0, 0, 0));
|
||||
endDate = new Date(now.setHours(23, 59, 59, 999));
|
||||
timeRangeName = 'today';
|
||||
break;
|
||||
case 'last2days':
|
||||
startDate = new Date(now.setDate(now.getDate() - 2));
|
||||
endDate = new Date();
|
||||
timeRangeName = 'last 2 days';
|
||||
break;
|
||||
case 'last7days':
|
||||
startDate = new Date(now.setDate(now.getDate() - 7));
|
||||
endDate = new Date();
|
||||
timeRangeName = 'last 7 days';
|
||||
break;
|
||||
case 'thisMonth':
|
||||
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
endDate = new Date();
|
||||
timeRangeName = 'this month so far';
|
||||
break;
|
||||
case 'thisYear':
|
||||
startDate = new Date(now.getFullYear(), 0, 1);
|
||||
endDate = new Date();
|
||||
timeRangeName = 'this year so far';
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// We set the date input fields to match the selected period
|
||||
document.getElementById('start-date').value = startDate.toISOString().slice(0, 10);
|
||||
document.getElementById('end-date').value = endDate.toISOString().slice(0, 10);
|
||||
|
||||
// Loop through all graphs and update their time range and label
|
||||
graphs.forEach(function(graphObj) {
|
||||
graphObj.graph.options.scales.x.min = startDate;
|
||||
graphObj.graph.options.scales.x.max = endDate;
|
||||
graphObj.graph.update();
|
||||
updatePeriodLabel(graphObj.graph, graphObj.label); // Update the period label
|
||||
});
|
||||
}
|
||||
|
||||
// Custom date range
|
||||
function setCustomTimeRange() {
|
||||
var startDate = document.getElementById('start-date').value;
|
||||
var endDate = document.getElementById('end-date').value;
|
||||
|
||||
if (!startDate || !endDate) return;
|
||||
|
||||
// Convert the input dates to JavaScript Date objects
|
||||
startDate = new Date(startDate);
|
||||
endDate = new Date(endDate);
|
||||
timeRangeName = 'custom range';
|
||||
|
||||
// Loop through all graphs and update the custom time range
|
||||
graphs.forEach(function(graphObj) {
|
||||
graphObj.graph.options.scales.x.min = startDate;
|
||||
graphObj.graph.options.scales.x.max = endDate;
|
||||
graphObj.graph.update();
|
||||
updatePeriodLabel(graphObj.graph, graphObj.label); // Update the period label
|
||||
});
|
||||
}
|
||||
|
||||
// Set the clicked button state to active
|
||||
function setActive(element) {
|
||||
// Remove 'active' class from all buttons
|
||||
var buttons = document.querySelectorAll('.button');
|
||||
buttons.forEach(function(btn) {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
|
||||
// Add 'active' class only to the clicked button
|
||||
element.classList.add('active');
|
||||
}
|
||||
|
||||
// Call setTimeRange('last7days') on page load to pre-load last 7 days by default
|
||||
window.onload = function() {
|
||||
setTimeRange('last7days');
|
||||
};
|
||||
</script>
|
|
@ -1,53 +0,0 @@
|
|||
|
||||
<!-- help -->
|
||||
<div class="card text-center w-100 mx-auto">
|
||||
|
||||
<p class="h4 card-header">Jilo Help</p>
|
||||
<div class="card-body">
|
||||
|
||||
<div style="text-align: left; font-family: monospace; font-size: 0.75em; white-space: pre-wrap;">
|
||||
<a href="https://lindeas.com/jilo">Jilo</a> is a software tools suite developed by <a href="https://lindeas.com">Lindeas Ltd.</a> designed to help in maintaining a Jitsi Meet platform.
|
||||
|
||||
It consists of several parts meant to run together, although some of them can be used separately.
|
||||
|
||||
<hr /><strong>"JILO"</strong>
|
||||
|
||||
This is the command-line tool for extracting information about important events from the Jitsi Meet log files, storing them in a database and searching through that database.
|
||||
Jilo is written in Bash and has very minimal external dependencies. That means that you can run it on almost any Linux system with jitsi log files.
|
||||
|
||||
It can either:
|
||||
- show the data directly in the terminal,
|
||||
- provide it to an instance of the web application "Jilo Web" for displaying statistics (the Jilo Web server needs to have access to the sqlite database file from Jilo),
|
||||
- or send the data output to a "Jilo Agent" that can then allow a remote Jilo Web access it.
|
||||
|
||||
This way Jilo is always available on each host in the Jitsi Meet platform for quick command-line search, while also providing data for the statistics on a central Jilo Web server, without any need to put additional software on each server.
|
||||
|
||||
<hr /><strong>"Jilo Agent"</strong>
|
||||
|
||||
The Jilo Agent is a small program, written in Go. It runs on remote servers in the Jitsi Meet platform, and provides info about the operation of the different components of the platform.
|
||||
|
||||
It listens for connections from the central Jilo Web app on a special port and the connection is secured with JWT tokens authentication. It can be configured to use HTTPS. In a firewall you only need to allow the agent's port for incoming connections from the Jilo Web server.
|
||||
|
||||
All information about the different services (jvb, jicofo, jigasi, nginx, prosody) is transmitted over that single port. This, plus the authentication and the fact that Jilo Agent doesn't need any additional external programs or libraries to operate, make it very easy for deploying and automating the deployment in a large Jitsi Meet setup.
|
||||
|
||||
<hr /><strong>"Jilo Web"</strong>
|
||||
|
||||
Jilo Web is the web app that combines all the information received from Jilo and Jilo Agents and shows statistics and graphs of the usage, the events and the issues.
|
||||
|
||||
It's a multi-user web tool with user levels and access rights integrated into it, making it suitable for the different levels in an enterprise.
|
||||
|
||||
The current website you are looking at is running a Jilo Web instance.
|
||||
|
||||
<hr /><strong>"Jilo Server"</strong>
|
||||
|
||||
Jilo Server is a server component written in Go, meant to work alongside Jilo Web. It is responsible for all automated tasks - health checks, periodic retrieval of data from the remote Jilo Agents, etc.
|
||||
|
||||
It generally works on the same machine as the web interface Jilo Web and shares its database, although if needed it could be deployed on a separate machine.
|
||||
|
||||
Jilo Web checks for the Jilo Server availability and displays a warning if there is a problem with the server.
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /help -->
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
</div>
|
||||
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<div class="mb-5">
|
||||
<hr /><p class="m-3">NB: This functionality is still under development. The data is just an example.</p><hr /><!-- FIXME remove when implemented -->
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col"></th>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<th scope="col"><?= htmlspecialchars($record['table_headers']) ?></th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>conferences</td>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<td><?php if (!empty($record['conferences'])) { ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&from_time=<?= htmlspecialchars($record['from_time']) ?>&until_time=<?= htmlspecialchars($record['until_time']) ?>"><?= htmlspecialchars($record['conferences']) ?></a> <?php } else { ?>
|
||||
0<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>participants</td>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<td><?php if (!empty($record['participants'])) { ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&from_time=<?= htmlspecialchars($record['from_time']) ?>&until_time=<?= htmlspecialchars($record['until_time']) ?>"><?= htmlspecialchars($record['participants']) ?></a> <?php } else { ?>
|
||||
0<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
<!-- Logs filter -->
|
||||
<div class="card w-auto bg-light border-light card-body text-right" style="text-align: right;">
|
||||
<form method="POST" id="filter_form" class="filter-results" action="?page=logs">
|
||||
<label for="from_time">from</label>
|
||||
<input type="date" id="from_time" name="from_time"<?php if (isset($_REQUEST['from_time'])) echo " value=\"" . htmlspecialchars($from_time) . "\"" ?> />
|
||||
<label for="until_time">until</label>
|
||||
<input type="date" id="until_time" name="until_time"<?php if (isset($_REQUEST['until_time'])) echo " value=\"" . htmlspecialchars($until_time) . "\"" ?> />
|
||||
<input type="text" name="id" placeholder="user ID"<?php if (isset($_REQUEST['id'])) echo " value=\"" . htmlspecialchars($_REQUEST['id']) . "\"" ?> />
|
||||
<input type="text" name="message" placeholder="message"<?php if (isset($_REQUEST['message'])) echo " value=\"" . htmlspecialchars($_REQUEST['message']) . "\"" ?> />
|
||||
<input type="button" onclick="clearFilter()" value="clear" />
|
||||
<input type="submit" value="search" />
|
||||
</form>
|
||||
<script>
|
||||
function clearFilter() {
|
||||
document.getElementById("filter_form").reset();
|
||||
const filterFields = document.querySelectorAll("#filter_form input");
|
||||
filterFields.forEach(input => {
|
||||
if (input.type === 'text' ||input.type === 'date') {
|
||||
input.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<!-- /Logs filter -->
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
<div class="row">
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapse<?= htmlspecialchars($widget['name']) ?>" role="button" aria-expanded="true" aria-controls="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<div class="card w-auto bg-light card-body" style="flex-direction: row;"><?= htmlspecialchars($widget['title']) ?></div>
|
||||
<?php } else { ?>
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= htmlspecialchars($widget['title']) ?></div>
|
||||
<?php } ?>
|
||||
<?php if ($widget['filter'] === true) {
|
||||
include '../app/templates/logs-filter.php'; } ?>
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<p class="m-3">time period: <strong><?= htmlspecialchars($from_time) ?> - <?= htmlspecialchars($until_time) ?></strong></p>
|
||||
<?php } ?>
|
||||
<div class="mb-5">
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<?php foreach ($widget['table_headers'] as $header) { ?>
|
||||
<th scope="col" class="th-<?= htmlspecialchars($header) ?>"><?= htmlspecialchars($header) ?></th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($widget['table_records'] as $row) { ?>
|
||||
<tr>
|
||||
<?php
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'user ID' && isset($user_id) && $user_id === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } else { ?>
|
||||
<td><?= htmlspecialchars($column ?? '') ?></td>
|
||||
<?php }
|
||||
} ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
if ($widget['pagination'] && $item_count > $items_per_page) {
|
||||
$url = "$app_root?platform=$platform_id&page=$page";
|
||||
include '../app/helpers/pagination.php';
|
||||
}
|
||||
?>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<?php } ?>
|
||||
<!-- Footer -->
|
||||
<div id="footer">Jilo Web <?= htmlspecialchars($config['version']) ?> ©2024 - web interface for <a href="https://lindeas.com/jilo">Jilo</a></div>
|
||||
<div id="footer">Jilo Web <?= $config['version'] ?> ©2024 - web interface for <a href="https://lindeas.com/jilo">Jilo</a></div>
|
||||
<!-- /Footer -->
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2,14 +2,8 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/bootstrap/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/main.css">
|
||||
<?php if ($page === 'logs') { ?>
|
||||
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/logs.css">
|
||||
<?php } ?>
|
||||
<?php if ($page === 'profile') { ?>
|
||||
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/profile.css">
|
||||
<?php } ?>
|
||||
<link rel="stylesheet" type="text/css" href="<?= $app_root ?>static/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="<?= $app_root ?>static/all.css">
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||
|
@ -23,17 +17,9 @@
|
|||
}
|
||||
})();
|
||||
</script>
|
||||
<?php if ($page === 'agents') { ?>
|
||||
<script src="<?= htmlspecialchars($app_root) ?>static/agents.js"></script>
|
||||
<?php } ?>
|
||||
<?php if ($page === 'graphs') { ?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.1"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.0"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@1.2.1/dist/chartjs-plugin-zoom.min.js"></script>
|
||||
<?php } ?>
|
||||
<title>Jilo Web</title>
|
||||
<link rel="icon" type="image/x-icon" href="<?= htmlspecialchars($app_root) ?>static/favicon.ico">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
|
|
@ -1,32 +1,22 @@
|
|||
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Menu -->
|
||||
<div class="menu-container">
|
||||
<ul class="menu-left">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>" class="logo-link"><div class="col-4"><img class="logo" src="<?= htmlspecialchars($app_root) ?>static/jilo-logo.png" alt="JILO"/></div></a>
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id?>" class="logo-link"><div class="col-4"><img class="logo" src="<?= $app_root ?>static/jilo-logo.png" alt="JILO"/></div></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<li class="font-weight-light text-uppercase" style="font-size: 0.5em; color: whitesmoke; margin-right: 70px; align-content: center;">version <?= htmlspecialchars($config['version']) ?></li>
|
||||
<li class="font-weight-light text-uppercase" style="font-size: 0.5em; color: whitesmoke; margin-right: 70px; align-content: center;">version <?php echo $config['version']; ?></li>
|
||||
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
|
||||
<?php foreach ($platformsAll as $platform) {
|
||||
$platform_switch_url = switchPlatform($platform['id']);
|
||||
?>
|
||||
<?php foreach ($config['platforms'] as $index => $platform) { ?>
|
||||
<li style="margin-right: 3px;">
|
||||
<?php if ((isset($_REQUEST['platform']) || empty($_SERVER['QUERY_STRING'])) && $platform['id'] == $platform_id) { ?>
|
||||
<span style="background-color: #fff; border: 1px solid #111; color: #111; border-bottom-color: #fff; padding-bottom: 12px;">
|
||||
<?= htmlspecialchars($platform['name']) ?>
|
||||
</span>
|
||||
<?php } else { ?>
|
||||
<a href="<?= htmlspecialchars($platform_switch_url) ?>">
|
||||
<a style="background-color: #111;" href="?platform=<?= htmlspecialchars($index) ?>&page=front">
|
||||
<?= htmlspecialchars($platform['name']) ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
|
@ -35,11 +25,11 @@
|
|||
|
||||
<ul class="menu-right">
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
<li><a href="<?= htmlspecialchars($app_root) ?>?page=profile"><?= htmlspecialchars($currentUser) ?></a></li>
|
||||
<li><a href="<?= htmlspecialchars($app_root) ?>?page=logout">logout</a></li>
|
||||
<li><a href="<?= $app_root ?>?page=profile"><?= $user ?></a></li>
|
||||
<li><a href="<?= $app_root ?>?page=logout">logout</a></li>
|
||||
<?php } else { ?>
|
||||
<li><a href="<?= htmlspecialchars($app_root) ?>?page=login">login</a></li>
|
||||
<li><a href="<?= htmlspecialchars($app_root) ?>?page=register">register</a></li>
|
||||
<li><a href="<?= $app_root ?>?page=login">login</a></li>
|
||||
<li><a href="<?= $app_root ?>?page=register">register</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -2,100 +2,58 @@
|
|||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-md-3 sidebar-wrapper bg-light" id="sidebar">
|
||||
<div class="text-center" style="border: 1px solid #0dcaf0; height: 22px;" id="time_now">
|
||||
<?php
|
||||
$timeNow = new DateTime('now', new DateTimeZone($userTimezone));
|
||||
?>
|
||||
<!--span style="vertical-align: top; font-size: 12px;"><?= htmlspecialchars($timeNow->format('d M Y H:i')) ?> <?= htmlspecialchars($userTimezone) ?></span-->
|
||||
<span style="vertical-align: top; font-size: 12px;"><?= htmlspecialchars($timeNow->format('H:i')) ?> <?= htmlspecialchars($userTimezone) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="col-4"><button class="btn btn-sm btn-info toggle-sidebar-button" type="button" id="toggleSidebarButton" value=">>"></button></div>
|
||||
<div class="sidebar-content card ml-3 mt-3">
|
||||
<ul class="list-group">
|
||||
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=dashboard">
|
||||
<li class="list-group-item<?php if ($page === 'dashboard') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>statistics</small></p></li>
|
||||
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=front">
|
||||
<li class="list-group-item<?php if ($page === 'front') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-chart-line" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="general jitsi stats"></i>general stats
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>logs statistics</small></p></li>
|
||||
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences">
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=conferences">
|
||||
<li class="list-group-item<?php if ($page === 'conferences') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-video" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="conferences"></i>conferences
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants">
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=participants">
|
||||
<li class="list-group-item<?php if ($page === 'participants') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-users" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="participants"></i>participants
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=components">
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=components">
|
||||
<li class="list-group-item<?php if ($page === 'components') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-puzzle-piece" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="components"></i>components
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>graphs</small></p></li>
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>jilo-web config</small></p></li>
|
||||
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=graphs">
|
||||
<li class="list-group-item<?php if ($page === 'graphs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-chart-bar" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="combined graphs"></i>combined graphs
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=latest">
|
||||
<li class="list-group-item<?php if ($page === 'latest') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-list" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="latest data"></i>latest data
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>live data</small></p></li>
|
||||
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs">
|
||||
<li class="list-group-item<?php if ($page === 'config' && $item === 'configjs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-tv" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="config.js"></i>config.js
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs">
|
||||
<li class="list-group-item<?php if ($page === 'config' && $item === 'interfaceconfigjs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-th" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="interface_config.js"></i>interface_config.js
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=agents">
|
||||
<li class="list-group-item<?php if ($page === 'agents') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-mask" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="jilo agents"></i>jilo agents
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>system</small></p></li>
|
||||
|
||||
<?php if ($userObject->hasRight($user_id, 'view config file')) {?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=config">
|
||||
<a href="<?= $app_root ?>?page=config">
|
||||
<li class="list-group-item<?php if ($page === 'config' && $item === '') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-wrench" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="configuration"></i>config
|
||||
</li>
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=status">
|
||||
<li class="list-group-item<?php if ($page === 'status' && $item === '') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-heartbeat" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="status"></i>status
|
||||
</li>
|
||||
</a>
|
||||
<?php if ($userObject->hasRight($user_id, 'view app logs')) {?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=logs">
|
||||
<a href="<?= $app_root ?>?page=logs">
|
||||
<li class="list-group-item<?php if ($page === 'logs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-shoe-prints" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="logs"></i>logs
|
||||
</li>
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=help">
|
||||
<li class="list-group-item<?php if ($page === 'help') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-question-circle" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="help"></i>help
|
||||
<i class="fas fa-list" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="logs"></i>logs
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<li class="list-group-item bg-light" style="border: none;"><p class="text-end mb-0"><small>current Jitsi platform</small></p></li>
|
||||
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=config&item=configjs">
|
||||
<li class="list-group-item<?php if ($page === 'config' && $item === 'configjs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-tv" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="configuration"></i>config.js
|
||||
</li>
|
||||
</a>
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id ?>&page=config&item=interfaceconfigjs">
|
||||
<li class="list-group-item<?php if ($page === 'config' && $item === 'interfaceconfigjs') echo ' list-group-item-secondary'; else echo ' list-group-item-action'; ?>">
|
||||
<i class="fas fa-th" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="configuration"></i>interface_config.js
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
|
||||
<!-- user profile -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
|
||||
<p class="h4 card-header">Profile of <?= htmlspecialchars($userDetails[0]['username']) ?></p>
|
||||
<div class="card-body">
|
||||
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?page=profile" enctype="multipart/form-data">
|
||||
<div class="row">
|
||||
<p class="border rounded bg-light mb-4"><small>edit the profile fields</small></p>
|
||||
<div class="col-md-4 avatar-container">
|
||||
<div class="avatar-wrapper">
|
||||
<img class="avatar-img" src="<?= htmlspecialchars($app_root) . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||
<div class="avatar-btn-container">
|
||||
|
||||
<label for="avatar-upload" class="avatar-btn avatar-btn-select btn btn-primary">
|
||||
<i class="fas fa-folder" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="select new avatar"></i>
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" name="avatar_file" accept="image/*" style="display:none;">
|
||||
|
||||
<?php if ($default_avatar) { ?>
|
||||
<button type="button" class="avatar-btn avatar-btn-remove btn btn-secondary" data-toggle="modal" data-target="#confirmDeleteModal" disabled>
|
||||
<?php } else { ?>
|
||||
<button type="button" class="avatar-btn avatar-btn-remove btn btn-danger" data-toggle="modal" data-target="#confirmDeleteModal">
|
||||
<?php } ?>
|
||||
<i class="fas fa-trash" data-toggle="tooltip" data-placement="right" data-offset="30.0" title="remove current avatar"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<!--div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="username" class="form-label"><small>username:</small></label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<input class="form-control" type="text" name="username" value="<?= htmlspecialchars($userDetails[0]['username']) ?>" required />
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="name" class="form-label"><small>name:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<input class="form-control" type="text" name="name" value="<?= htmlspecialchars($userDetails[0]['name']) ?>" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="email" class="form-label"><small>email:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<input class="form-control" type="text" name="email" value="<?= htmlspecialchars($userDetails[0]['email']) ?>" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="timezone" class="form-label"><small>timezone:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<select class="form-control" name="timezone" id="timezone">
|
||||
<?php foreach ($allTimezones as $timezone) { ?>
|
||||
<option value="<?= htmlspecialchars($timezone) ?>" <?= $timezone === $userTimezone ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($timezone) ?> (<?= htmlspecialchars(getUTCOffset($timezone)) ?>)
|
||||
</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="bio" class="form-label"><small>bio:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<textarea class="form-control" name="bio" rows="10"><?= htmlspecialchars($userDetails[0]['bio'] ?? '') ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="rights" class="form-label"><small>rights:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?php foreach ($allRights as $right) {
|
||||
// Check if the current right exists in $userRights
|
||||
$isChecked = false;
|
||||
foreach ($userRights as $userRight) {
|
||||
if ($userRight['right_id'] === $right['right_id']) {
|
||||
$isChecked = true;
|
||||
break;
|
||||
}
|
||||
} ?>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="rights[]" value="<?= htmlspecialchars($right['right_id']) ?>" id="right_<?= htmlspecialchars($right['right_id']) ?>" <?= $isChecked ? 'checked' : '' ?> />
|
||||
<label class="form-check-label" for="right_<?= htmlspecialchars($right['right_id']) ?>"><?= htmlspecialchars($right['right_name']) ?></label>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=profile" class="btn btn-secondary">Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- avatar removal modal confirmation -->
|
||||
<div class="modal fade" id="confirmDeleteModal" tabindex="-1" aria-labelledby="confirmDeleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="confirmDeleteModalLabel">Confirm Avatar Deletion</h5>
|
||||
<button type="button" class="btn-close" data-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<img class="avatar-img" src="<?= htmlspecialchars($app_root) . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||
<br />
|
||||
Are you sure you want to delete your avatar?
|
||||
<br />
|
||||
This action cannot be undone.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<form id="remove-avatar-form" data-action="remove-avatar" method="POST" action="<?= htmlspecialchars($app_root) ?>?page=profile&action=remove&item=avatar">
|
||||
<button type="button" class="btn btn-danger" id="confirm-delete">Delete Avatar</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /user profile -->
|
||||
|
||||
<script>
|
||||
// Preview the uploaded avatar
|
||||
document.getElementById('avatar-upload').addEventListener('change', function(event) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
document.querySelector('.avatar-img').src = reader.result;
|
||||
};
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
});
|
||||
|
||||
// Avatar file size and type control
|
||||
document.getElementById('avatar-upload').addEventListener('change', function() {
|
||||
const maxFileSize = 500 * 1024; // 500 KB in bytes
|
||||
const currentAvatar = '<?= htmlspecialchars($app_root) . htmlspecialchars($avatar) ?>'; // current avatar
|
||||
const file = this.files[0];
|
||||
|
||||
if (file) {
|
||||
// Check file size
|
||||
if (file.size > maxFileSize) {
|
||||
alert('File size exceeds 500 KB. Please select a smaller file.');
|
||||
this.value = ''; // Clear the file input
|
||||
document.querySelector('.avatar-img').src = currentAvatar;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Submitting the avatar deletion confirmation modal form
|
||||
document.getElementById('confirm-delete').addEventListener('click', function(event) {
|
||||
event.preventDefault(); // Prevent the outer form from submitting
|
||||
document.getElementById('remove-avatar-form').submit();
|
||||
});
|
||||
|
||||
// Function to detect user's timezone and select it in the dropdown
|
||||
function setTimezone() {
|
||||
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const timezoneSelect = document.getElementById("timezone");
|
||||
timezoneSelect.className = 'form-control border border-danger';
|
||||
|
||||
// Loop through the options to find and select the user's timezone
|
||||
for (let i = 0; i < timezoneSelect.options.length; i++) {
|
||||
if (timezoneSelect.options[i].value === userTimezone) {
|
||||
timezoneSelect.selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run the function on page load
|
||||
window.onload = function() {
|
||||
const isTimezoneSet = <?php echo json_encode($isTimezoneSet); ?>; // Pass PHP flag to JavaScript
|
||||
// If timezone is not set, run setTimezone()
|
||||
if (!isTimezoneSet) {
|
||||
setTimezone();
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
<!-- user profile -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
|
||||
<p class="h4 card-header">Profile of <?= htmlspecialchars($userDetails[0]['username']) ?></p>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 avatar-container">
|
||||
<div>
|
||||
<img class="avatar-img" src="<?= htmlspecialchars($app_root) . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
|
||||
<!--div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>username:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?= htmlspecialchars($userDetails[0]['username']) ?>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>name:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?= htmlspecialchars($userDetails[0]['name']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>email:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?= htmlspecialchars($userDetails[0]['email']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>timezone:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?php if (isset($userDetails[0]['timezone'])) { ?>
|
||||
<?= htmlspecialchars($userDetails[0]['timezone']) ?> <span style="font-size: 0.66em;">(<?= htmlspecialchars(getUTCOffset($userDetails[0]['timezone'])) ?>)</span>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>bio:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<textarea class="scroll-box" rows="10" readonly><?= htmlspecialchars($userDetails[0]['bio'] ?? '') ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label class="form-label"><small>rights:</small></label>
|
||||
</div>
|
||||
<div class="col-md-8 text-start bg-light">
|
||||
<?php foreach ($userRights as $right) { ?>
|
||||
<?= htmlspecialchars($right['right_name'] ?? '') ?>
|
||||
<br />
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=profile&action=edit" class="btn btn-primary">Edit</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /user profile -->
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
<!-- jilo agent status -->
|
||||
<div class="card text-center w-75 mx-lef" style="padding-left: 80px;">
|
||||
<div class="card-body">
|
||||
<p class="card-text text-left" style="text-align: left;">
|
||||
Jilo Agent <a href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform['id']) ?>agent<?= htmlspecialchars($agent['id']) ?>"><?= htmlspecialchars($agent['agent_description']) ?></a>:
|
||||
<strong><?= $agent_availability ?></strong>
|
||||
<br />
|
||||
host: <strong><?= htmlspecialchars($agent_host) ?></strong>,
|
||||
port: <strong><?= htmlspecialchars($agent_port) ?></strong>,
|
||||
endpoint: <strong><?= htmlspecialchars($agent['agent_endpoint']) ?></strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
<!-- jitsi platform status -->
|
||||
<br />
|
||||
<div class="card text-center w-75 mx-lef" style="padding-left: 40px;">
|
||||
<div class="card-body">
|
||||
<p class="card-text text-left" style="text-align: left;">
|
||||
Jitsi Meet platform: <a href="<?= htmlspecialchars($app_root) ?>?page=config#platform<?= htmlspecialchars($platform['id']) ?>"><?= htmlspecialchars($platform['name']) ?></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
<!-- jilo status -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<p class="h4 card-header">Jilo platform status</p>
|
||||
<div class="card-body">
|
||||
<p class="card-text text-left" style="text-align: left;">
|
||||
Jilo Server:
|
||||
<?php if ($server_status) { ?>
|
||||
<strong><span class="text-success">running</span></strong>
|
||||
<?php } else { ?>
|
||||
<strong><span class="text-danger">not running</span></strong>
|
||||
<?php } ?>
|
||||
<br />
|
||||
host: <strong><?= htmlspecialchars($server_host) ?></strong>,
|
||||
port: <strong><?= htmlspecialchars($server_port) ?></strong>,
|
||||
endpoint: <strong><?= htmlspecialchars($server_endpoint) ?></strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
|
@ -2,27 +2,27 @@
|
|||
<div class="row">
|
||||
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapse<?= htmlspecialchars($widget['name']) ?>" role="button" aria-expanded="true" aria-controls="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapse<?= $widget['name'] ?>" role="button" aria-expanded="true" aria-controls="collapse<?= $widget['name'] ?>">
|
||||
<div class="card w-auto bg-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
<?php } else { ?>
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
<?php } ?>
|
||||
<?php if ($widget['filter'] === true) {
|
||||
include '../app/templates/block-results-filter.php'; } ?>
|
||||
include('../app/templates/block-results-filter.php'); } ?>
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<!-- widget "<?= $widget['name']; ?>" -->
|
||||
<div class="collapse show" id="collapse<?= $widget['name'] ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<p class="m-3">time period: <strong><?= htmlspecialchars($from_time) ?> - <?= htmlspecialchars($until_time) ?></strong></p>
|
||||
<p class="m-3">time period: <strong><?= $from_time ?> - <?= $until_time ?></strong></p>
|
||||
<?php } ?>
|
||||
<div class="mb-5">
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col"></th>
|
||||
|
@ -36,7 +36,7 @@
|
|||
<td>conferences</td>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<td><?php if (!empty($record['conferences'])) { ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&from_time=<?= htmlspecialchars($record['from_time']) ?>&until_time=<?= htmlspecialchars($record['until_time']) ?>"><?= htmlspecialchars($record['conferences']) ?></a> <?php } else { ?>
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=conferences&from_time=<?= $record['from_time'] ?>&until_time=<?= $record['until_time'] ?>"><?= htmlspecialchars($record['conferences']) ?></a> <?php } else { ?>
|
||||
0<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<td>participants</td>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<td><?php if (!empty($record['participants'])) { ?>
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&from_time=<?= htmlspecialchars($record['from_time']) ?>&until_time=<?= htmlspecialchars($record['until_time']) ?>"><?= htmlspecialchars($record['participants']) ?></a> <?php } else { ?>
|
||||
<a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&from_time=<?= $record['from_time'] ?>&until_time=<?= $record['until_time'] ?>"><?= htmlspecialchars($record['participants']) ?></a> <?php } else { ?>
|
||||
0<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
|
@ -57,4 +57,4 @@
|
|||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<!-- /widget "<?= $widget['name']; ?>" -->
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
<!-- widget "user profile" -->
|
||||
<div>
|
||||
<p>Profile of <?= $user ?></p>
|
||||
<ul>
|
||||
<li>username: <?= $_SESSION['username'] ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /widget "user profile" -->
|
|
@ -1,26 +1,26 @@
|
|||
|
||||
<div class="row">
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapse<?= htmlspecialchars($widget['name']) ?>" role="button" aria-expanded="true" aria-controls="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<a style="text-decoration: none;" data-toggle="collapse" href="#collapse<?= $widget['name'] ?>" role="button" aria-expanded="true" aria-controls="collapse<?= $widget['name'] ?>">
|
||||
<div class="card w-auto bg-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
<?php } else { ?>
|
||||
<div class="card w-auto bg-light border-light card-body" style="flex-direction: row;"><?= $widget['title'] ?></div>
|
||||
<?php } ?>
|
||||
<?php if ($widget['filter'] === true) {
|
||||
include '../app/templates/block-results-filter.php'; } ?>
|
||||
include('../app/templates/block-results-filter.php'); } ?>
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<div class="collapse show" id="collapse<?= htmlspecialchars($widget['name']) ?>">
|
||||
<!-- widget "<?= $widget['name']; ?>" -->
|
||||
<div class="collapse show" id="collapse<?= $widget['name'] ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<p class="m-3">time period: <strong><?= htmlspecialchars($from_time) ?> - <?= htmlspecialchars($until_time) ?></strong></p>
|
||||
<p class="m-3">time period: <strong><?= $from_time ?> - <?= $until_time ?></strong></p>
|
||||
<?php } ?>
|
||||
<div class="mb-5">
|
||||
<?php if ($widget['full'] === true) { ?>
|
||||
<table class="table table-results table-striped table-hover table-bordered">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<?php foreach ($widget['table_headers'] as $header) { ?>
|
||||
|
@ -39,31 +39,27 @@
|
|||
if ($key === 'conference ID' && isset($conferenceId) && $conferenceId === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($key === 'conference ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=conferences&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'conference name' && isset($conferenceName) && $conferenceName === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($key === 'conference name') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=conferences&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=conferences&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'participant ID' && isset($participantId) && $participantId === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($key === 'participant ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'component ID') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=components&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=components&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($stats_id && $key === 'parameter' && isset($participantName) && $participantName === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($stats_id && $key === 'parameter') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($participant_ip && $key === 'parameter' && isset($participantIp) && $participantIp === $column) { ?>
|
||||
<td><strong><?= htmlspecialchars($column ?? '') ?></strong></td>
|
||||
<?php } elseif ($participant_ip && $key === 'parameter') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=participants&ip=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&ip=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'component') { ?>
|
||||
<td><a href="<?= htmlspecialchars($app_root) ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=components&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php
|
||||
// in general listings we don't show seconds and miliseconds
|
||||
} elseif ($key === 'start' || $key === 'end') { ?>
|
||||
<td><?= htmlspecialchars(substr($column ?? '', 0, -7)) ?></td>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=components&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } else { ?>
|
||||
<td><?= htmlspecialchars($column ?? '') ?></td>
|
||||
<?php }
|
||||
|
@ -72,15 +68,9 @@
|
|||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
if ($widget['pagination'] && $item_count > $items_per_page) {
|
||||
$url = "$app_root?platform=$platform_id&page=$page";
|
||||
include '../app/helpers/pagination.php';
|
||||
}
|
||||
?>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= htmlspecialchars($widget['name']) ?>" -->
|
||||
<!-- /widget "<?= $widget['name']; ?>" -->
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
INSERT INTO jilo_agent_types VALUES(1,'jvb','/jvb');
|
||||
INSERT INTO jilo_agent_types VALUES(2,'jicofo','/jicofo');
|
||||
INSERT INTO jilo_agent_types VALUES(3,'prosody','/prosody');
|
||||
INSERT INTO jilo_agent_types VALUES(4,'nginx','/nginx');
|
||||
INSERT INTO jilo_agent_types VALUES(5,'jibri','/jibri');
|
|
@ -1,13 +0,0 @@
|
|||
INSERT INTO rights VALUES(1,'superuser');
|
||||
INSERT INTO rights VALUES(2,'edit users');
|
||||
INSERT INTO rights VALUES(3,'view config file');
|
||||
INSERT INTO rights VALUES(4,'edit config file');
|
||||
INSERT INTO rights VALUES(5,'view own profile');
|
||||
INSERT INTO rights VALUES(6,'edit own profile');
|
||||
INSERT INTO rights VALUES(7,'view all profiles');
|
||||
INSERT INTO rights VALUES(8,'edit all profiles');
|
||||
INSERT INTO rights VALUES(9,'view app logs');
|
||||
INSERT INTO rights VALUES(10,'view all platforms');
|
||||
INSERT INTO rights VALUES(11,'edit all platforms');
|
||||
INSERT INTO rights VALUES(12,'view all agents');
|
||||
INSERT INTO rights VALUES(13,'edit all agents');
|
|
@ -1,65 +1,5 @@
|
|||
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE users_meta (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
name TEXT,
|
||||
email TEXT,
|
||||
timezone TEXT,
|
||||
avatar TEXT,
|
||||
bio TEXT,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
CREATE TABLE users_rights (
|
||||
user_id INTEGER,
|
||||
right_id INTEGER,
|
||||
PRIMARY KEY (user_id, right_id),
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (right_id) REFERENCES rights(id)
|
||||
);
|
||||
CREATE TABLE rights (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE
|
||||
);
|
||||
CREATE TABLE platforms (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
jitsi_url TEXT NOT NULL,
|
||||
jilo_database TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE jilo_agents (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
platform_id INTEGER NOT NULL,
|
||||
agent_type_id INTEGER NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
secret_key TEXT,
|
||||
check_period INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (platform_id) REFERENCES platforms(id),
|
||||
FOREIGN KEY (agent_type_id) REFERENCES jilo_agent_types(id)
|
||||
);
|
||||
CREATE TABLE jilo_agent_types (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
description TEXT,
|
||||
endpoint TEXT
|
||||
);
|
||||
CREATE TABLE jilo_agent_checks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
agent_id INTEGER,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
status_code INTEGER,
|
||||
response_time_ms INTEGER,
|
||||
response_content TEXT,
|
||||
FOREIGN KEY (agent_id) REFERENCES jilo_agents(id)
|
||||
);
|
||||
CREATE TABLE logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGET NOT NULL,
|
||||
time TEXT DEFAULT (DATETIME('now')),
|
||||
scope TEXT NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Package: jilo-web
|
||||
Version: 0.2.1
|
||||
Version: 0.2
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.TH JILO-WEB "8" "October 2024" "jilo-web 0.2.1"
|
||||
.TH JILO-WEB "8" "August 2024" "jilo-web 0.2"
|
||||
.SH NAME
|
||||
jilo-web \- PHP frontent to jilo (jitsi logs observer) database.
|
||||
.SH DESCRIPTION
|
||||
|
@ -17,7 +17,7 @@ Written and maintained by Yasen Pramatarov <yasen@lindeas.com>
|
|||
https://lindeas.com/jilo
|
||||
|
||||
.SH VERSION
|
||||
0.2.1
|
||||
0.2
|
||||
|
||||
.SH SEE ALSO
|
||||
jilo(8), jilo-cli(8)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Name: jilo-web
|
||||
Version: 0.2.1
|
||||
Version: 0.2
|
||||
Release: 1%{?dist}
|
||||
Summary: Jitsi logs web observer
|
||||
|
||||
|
@ -54,8 +54,6 @@ cp %{sourcedir}/man-jilo.8 %{buildroot}/usr/share/man/man8/%{name}.8
|
|||
/usr/share/man/man8/%{name}.8.gz
|
||||
|
||||
%changelog
|
||||
* Thu Oct 17 2024 Yasen Pramatarov <yasen@lindeas.com> 0.2.1
|
||||
- Build of upstream v0.2.1
|
||||
* Sat Aug 31 2024 Yasen Pramatarov <yasen@lindeas.com> 0.2
|
||||
- Build of upstream v0.2
|
||||
* Thu Jul 25 2024 Yasen Pramatarov <yasen@lindeas.com> 0.1.1
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2024 Chart.js Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -8,18 +8,13 @@
|
|||
* License: GPLv2
|
||||
* Project URL: https://lindeas.com/jilo
|
||||
* Year: 2024
|
||||
* Version: 0.2.1
|
||||
* Version: 0.2
|
||||
*/
|
||||
|
||||
// we start output buffering and.
|
||||
// flush it later only when there is no redirect
|
||||
ob_start();
|
||||
|
||||
// sanitize all input vars that may end up in URLs or forms
|
||||
require '../app/helpers/sanitize.php';
|
||||
|
||||
require '../app/helpers/errors.php';
|
||||
|
||||
// error reporting, comment out in production
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
|
@ -28,26 +23,15 @@ error_reporting(E_ALL);
|
|||
// list of available pages
|
||||
// edit accordingly, add 'pages/PAGE.php'
|
||||
$allowed_urls = [
|
||||
'dashboard',
|
||||
|
||||
'conferences',
|
||||
'participants',
|
||||
'components',
|
||||
|
||||
'graphs',
|
||||
'latest',
|
||||
|
||||
'agents',
|
||||
|
||||
'profile',
|
||||
'config',
|
||||
'status',
|
||||
'logs',
|
||||
'help',
|
||||
|
||||
'front',
|
||||
'login',
|
||||
'logout',
|
||||
'register',
|
||||
'profile',
|
||||
'config',
|
||||
'conferences',
|
||||
'participants',
|
||||
'components',
|
||||
];
|
||||
|
||||
// cnfig file
|
||||
|
@ -78,51 +62,47 @@ $app_root = $config['folder'];
|
|||
session_name('jilo');
|
||||
session_start();
|
||||
|
||||
if (isset($_REQUEST['page'])) {
|
||||
$page = $_REQUEST['page'];
|
||||
} else {
|
||||
$page = 'front';
|
||||
}
|
||||
if (isset($_REQUEST['item'])) {
|
||||
$item = $_REQUEST['item'];
|
||||
} else {
|
||||
$item = '';
|
||||
}
|
||||
|
||||
// check if logged in
|
||||
unset($currentUser);
|
||||
unset($user);
|
||||
if (isset($_COOKIE['username'])) {
|
||||
if ( !isset($_SESSION['username']) ) {
|
||||
$_SESSION['username'] = $_COOKIE['username'];
|
||||
}
|
||||
$currentUser = htmlspecialchars($_SESSION['username']);
|
||||
$user = htmlspecialchars($_SESSION['username']);
|
||||
}
|
||||
|
||||
// redirect to login
|
||||
if ( !isset($_COOKIE['username']) && ($page !== 'login' && $page !== 'register') ) {
|
||||
header('Location: ' . htmlspecialchars($app_root) . '?page=login');
|
||||
header('Location: index.php?page=login');
|
||||
exit();
|
||||
}
|
||||
|
||||
// connect to db of Jilo Web
|
||||
require '../app/classes/database.php';
|
||||
require '../app/helpers/database.php';
|
||||
$dbWeb = connectDB($config);
|
||||
|
||||
// start logging
|
||||
require '../app/classes/log.php';
|
||||
include '../app/helpers/logs.php';
|
||||
$logObject = new Log($dbWeb);
|
||||
$user_IP = getUserIP();
|
||||
|
||||
// get platforms details
|
||||
require '../app/classes/platform.php';
|
||||
$platformObject = new Platform($dbWeb);
|
||||
$platformsAll = $platformObject->getPlatformDetails();
|
||||
|
||||
// by default we connect ot the first configured platform
|
||||
if ($platform_id == '') {
|
||||
$platform_id = $platformsAll[0]['id'];
|
||||
// we use 'notice' for all non-critical messages and 'error' for errors
|
||||
if (isset($_SESSION['notice'])) {
|
||||
$notice = $_SESSION['notice'];
|
||||
}
|
||||
if (isset($_SESSION['error'])) {
|
||||
$error = $_SESSION['error'];
|
||||
}
|
||||
|
||||
$platformDetails = $platformObject->getPlatformDetails($platform_id);
|
||||
// by default we connect ot the first configured platform
|
||||
$platform_id = $_REQUEST['platform'] ?? '0';
|
||||
|
||||
// init user functions
|
||||
require '../app/classes/user.php';
|
||||
include '../app/helpers/profile.php';
|
||||
$userObject = new User($dbWeb);
|
||||
|
||||
// logout is a special case, as we can't use session vars for notices
|
||||
if ($page == 'logout') {
|
||||
// page building
|
||||
if (in_array($page, $allowed_urls)) {
|
||||
// logout is a special case, as we can't use session vars for notices
|
||||
if ($page == 'logout') {
|
||||
|
||||
// clean up session
|
||||
session_unset();
|
||||
|
@ -130,58 +110,33 @@ if ($page == 'logout') {
|
|||
setcookie('username', "", time() - 100, $config['folder'], $config['domain'], isset($_SERVER['HTTPS']), true);
|
||||
|
||||
$notice = "You were logged out.<br />You can log in again.";
|
||||
$user_id = $userObject->getUserId($currentUser)[0]['id'];
|
||||
$logObject->insertLog($user_id, "Logout: User \"$currentUser\" logged out. IP: $user_IP", 'user');
|
||||
|
||||
include '../app/templates/page-header.php';
|
||||
include '../app/templates/page-menu.php';
|
||||
include '../app/templates/block-message.php';
|
||||
include '../app/pages/login.php';
|
||||
|
||||
} else {
|
||||
|
||||
// if user is logged in, we need user details and rights
|
||||
if (isset($currentUser)) {
|
||||
$user_id = $userObject->getUserId($currentUser)[0]['id'];
|
||||
$userDetails = $userObject->getUserDetails($user_id);
|
||||
$userRights = $userObject->getUserRights($user_id);
|
||||
$userTimezone = isset($userDetails[0]['timezone']) ? $userDetails[0]['timezone'] : 'UTC'; // Default to UTC if no timezone is set
|
||||
|
||||
// If by error a logged in user requests the login page
|
||||
if ($page === 'login') {
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
exit();
|
||||
}
|
||||
|
||||
// check if the Jilo Server is running
|
||||
require '../app/classes/server.php';
|
||||
$serverObject = new Server($dbWeb);
|
||||
|
||||
$server_host = '127.0.0.1';
|
||||
$server_port = '8080';
|
||||
$server_endpoint = '/health';
|
||||
$server_status = $serverObject->getServerStatus($server_host, $server_port, $server_endpoint);
|
||||
if (!$server_status) {
|
||||
$error = 'The Jilo Server is not running. Some data may be old and incorrect.';
|
||||
}
|
||||
}
|
||||
|
||||
// page building
|
||||
// all other normal pages
|
||||
} else {
|
||||
include '../app/templates/page-header.php';
|
||||
include '../app/templates/page-menu.php';
|
||||
include '../app/templates/block-message.php';
|
||||
if (isset($currentUser)) {
|
||||
if (isset($user)) {
|
||||
include '../app/templates/page-sidebar.php';
|
||||
}
|
||||
if (in_array($page, $allowed_urls)) {
|
||||
// all normal pages
|
||||
include "../app/pages/{$page}.php";
|
||||
} else {
|
||||
// the page is not in allowed urls, loading "not found" page
|
||||
include '../app/templates/error-notfound.php';
|
||||
}
|
||||
|
||||
// the page is not in allowed urls, loading front page
|
||||
} else {
|
||||
$error = 'The page "' . $page . '" is not found';
|
||||
include '../app/templates/page-header.php';
|
||||
include '../app/templates/page-menu.php';
|
||||
include '../app/templates/block-message.php';
|
||||
if (isset($user)) {
|
||||
include '../app/templates/page-sidebar.php';
|
||||
}
|
||||
include '../app/pages/front.php';
|
||||
}
|
||||
// end with the footer
|
||||
include '../app/templates/page-footer.php';
|
||||
|
||||
// flush the output buffer and show the page
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<?php
|
||||
phpinfo();
|
||||
?>
|
|
@ -1,218 +0,0 @@
|
|||
function fetchData(agent_id, url, endpoint, jwtToken, force = false) {
|
||||
// FIXME make use of force variable
|
||||
|
||||
let counter = 0;
|
||||
const loadCacheButton = document.getElementById('agent' + agent_id + '-cache');
|
||||
const clearCacheButton = document.getElementById('agent' + agent_id + '-clear');
|
||||
const resultElement = document.getElementById("result" + agent_id);
|
||||
const cacheInfoElement = document.getElementById("cacheInfo" + agent_id);
|
||||
|
||||
// Show loading text
|
||||
resultElement.innerHTML = "Loading... (0 seconds)";
|
||||
|
||||
// Create an interval to update the counter every second
|
||||
const intervalId = setInterval(() => {
|
||||
counter++;
|
||||
resultElement.innerHTML = `Loading... (${counter} seconds)`;
|
||||
}, 1000);
|
||||
|
||||
// Create an AJAX request
|
||||
var xhr = new XMLHttpRequest();
|
||||
const agentUrl = url + endpoint;
|
||||
|
||||
// DEBUG show the requested URL for debugging purpose
|
||||
//console.log("Requesting URL:", agentUrl);
|
||||
|
||||
// Handle invalid URL error
|
||||
try {
|
||||
xhr.open("POST", agentUrl, true);
|
||||
} catch (e) {
|
||||
clearInterval(intervalId); // Stop the counter on error
|
||||
resultElement.innerHTML = `Error: Invalid URL ${agentUrl}<br />` + e.message;
|
||||
return; // Exit the function early
|
||||
}
|
||||
|
||||
// send the token
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + jwtToken);
|
||||
|
||||
// Set a timeout in milliseconds (10 seconds = 10000 ms)
|
||||
xhr.timeout = 10000;
|
||||
|
||||
// Handle the request state change
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
clearInterval(intervalId); // Stop the counter when the request completes
|
||||
clearTimeout(requestTimeout); // Clear the timeout if response is received
|
||||
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
// Parse and display the result
|
||||
let result = JSON.parse(xhr.responseText);
|
||||
// DEBUG display the result
|
||||
//console.log(xhr.responseText);
|
||||
|
||||
if (result.error) {
|
||||
resultElement.innerHTML = "Error: " + result.error;
|
||||
} else {
|
||||
// show the result in the html
|
||||
resultElement.innerHTML = JSON.stringify(result, null, 2);
|
||||
|
||||
// we don't cache the /status
|
||||
if (endpoint !== '/status') {
|
||||
// get the cache timestamp from the session
|
||||
const now = Date.now();
|
||||
const cacheTimestamp = new Date(now);
|
||||
|
||||
// display the cache retrieval date and time
|
||||
const formattedDate = cacheTimestamp.toLocaleDateString();
|
||||
const formattedTime = cacheTimestamp.toLocaleTimeString();
|
||||
cacheInfoElement.style.display = '';
|
||||
cacheInfoElement.innerHTML = `cache refreshed on ${formattedDate} at ${formattedTime}`;
|
||||
|
||||
// show the cache buttons
|
||||
loadCacheButton.disabled = false;
|
||||
loadCacheButton.style.display = '';
|
||||
clearCacheButton.disabled = false;
|
||||
clearCacheButton.style.display = '';
|
||||
|
||||
// send the result to PHP to store in session
|
||||
saveResultToSession(result, agent_id);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Display the error
|
||||
resultElement.innerHTML = "Error: Response is not a valid JSON.<br />Response: " + xhr.responseText;
|
||||
console.error("error:", e);
|
||||
}
|
||||
} else {
|
||||
resultElement.innerHTML = `Error: Unable to fetch data from ${agentUrl}<br />Status Code: ${xhr.status}<br />Status Text: ${xhr.statusText}<br />Response: ${xhr.responseText}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network-level errors (e.g., connection refused)
|
||||
xhr.onerror = function() {
|
||||
clearInterval(intervalId); // Stop the counter on error
|
||||
resultElement.innerHTML = `Network Error:<br />Unable to connect to ${agentUrl}<br />Check network connection or try again later.`;
|
||||
};
|
||||
|
||||
// Handle the timeout event
|
||||
xhr.ontimeout = function() {
|
||||
clearInterval(intervalId); // Stop the counter on timeout
|
||||
resultElement.innerHTML = "Request timed out. Please try again.";
|
||||
};
|
||||
|
||||
// Additional manual timeout
|
||||
var requestTimeout = setTimeout(function() {
|
||||
if (xhr.readyState !== 4) {
|
||||
xhr.abort(); // Abort the request if still pending after timeout
|
||||
clearInterval(intervalId); // Stop the counter
|
||||
resultElement.innerHTML = "Request timed out.";
|
||||
}
|
||||
}, 10000); // 10 seconds
|
||||
|
||||
// Send the AJAX request, with force flag
|
||||
xhr.send("action=fetch&agent_id=" + agent_id + "&force=" + (force ? 'true' : 'false'));
|
||||
|
||||
// // If the request finishes quickly, set this up to show at least 1 second delay
|
||||
// setTimeout(function() {
|
||||
// if (counter === 0) {
|
||||
// counter++;
|
||||
// resultElement.innerHTML = `Loading... (${counter} seconds)`;
|
||||
// }
|
||||
// }, 1000); // Simulate a minimum 1 second delay for testing
|
||||
|
||||
}
|
||||
|
||||
|
||||
// load the result from cache
|
||||
function loadCache(agent_id) {
|
||||
const resultElement = document.getElementById("result" + agent_id);
|
||||
const cacheInfoElement = document.getElementById("cacheInfo" + agent_id);
|
||||
resultElement.innerHTML = "Loading cached data...";
|
||||
|
||||
// Fetch the cached data from PHP
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "static/loadcache.php?agent="+agent_id, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.status === 'success') {
|
||||
// Display the cached data
|
||||
resultElement.innerHTML = JSON.stringify(response.data, null, 2);
|
||||
|
||||
// Get the cache timestamp from the session
|
||||
const cacheTimestamp = new Date(response.cache_time * 1000);
|
||||
|
||||
// Display the cache retrieval date and time
|
||||
const formattedDate = cacheTimestamp.toLocaleDateString();
|
||||
const formattedTime = cacheTimestamp.toLocaleTimeString();
|
||||
cacheInfoElement.innerHTML = `cache retrieved on ${formattedDate} at ${formattedTime}`;
|
||||
|
||||
} else {
|
||||
resultElement.innerHTML = "No cached data found.";
|
||||
cacheInfoElement.innerHTML = "";
|
||||
}
|
||||
} catch (e) {
|
||||
resultElement.innerHTML = "Error loading cached data.";
|
||||
console.error("error:", e);
|
||||
}
|
||||
} else {
|
||||
resultElement.innerHTML = `Error: Unable to load cache. Status code: ${xhr.status}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
resultElement.innerHTML = "Network error occurred while fetching the cached data.";
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
|
||||
// clear cache
|
||||
function clearCache(agent_id) {
|
||||
const loadCacheButton = document.getElementById('agent' + agent_id + '-cache');
|
||||
const clearCacheButton = document.getElementById('agent' + agent_id + '-clear');
|
||||
const cacheInfoElement = document.getElementById('cacheInfo' + agent_id);
|
||||
const resultElement = document.getElementById("result" + agent_id);
|
||||
|
||||
saveResultToSession(null, agent_id);
|
||||
|
||||
// hides the cache buttons
|
||||
// FIXME add a check whether the saveResult function was successful
|
||||
loadCacheButton.disabled = true;
|
||||
loadCacheButton.style.display = 'none';
|
||||
clearCacheButton.disabled = true;
|
||||
clearCacheButton.style.display = 'none';
|
||||
cacheInfoElement.innerHTML = '';
|
||||
cacheInfoElement.style.display = 'none';
|
||||
resultElement.innerHTML = 'click a button to to display data from the agent.';
|
||||
}
|
||||
|
||||
|
||||
// we send result to PHP session, to be available to the whole app
|
||||
function saveResultToSession(result, agent_id) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "?page=agents&agent="+agent_id, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
console.log("Data saved to session successfully.");
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
console.error("Error saving data to session.");
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify(result));
|
||||
}
|
|
@ -1,10 +1,3 @@
|
|||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -32,7 +25,7 @@ html, body {
|
|||
color: white;
|
||||
}
|
||||
|
||||
.menu-left li a, .menu-left li span, .menu-right li a {
|
||||
.menu-left li a, .menu-right li a {
|
||||
display: block;
|
||||
color: white;
|
||||
text-align: center;
|
||||
|
@ -140,8 +133,7 @@ html, body {
|
|||
.main-content {
|
||||
flex-grow: 1;
|
||||
transition: width 0.5s ease;
|
||||
margin-bottom: 50px;
|
||||
/* width: 80%;*/
|
||||
width: 80%;
|
||||
}
|
||||
.main-content.expanded {
|
||||
width: calc(70% + 250px);
|
||||
|
@ -151,7 +143,7 @@ html, body {
|
|||
}
|
||||
|
||||
.logo {
|
||||
height: 36px;
|
||||
height: 35px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
@ -165,39 +157,3 @@ html, body {
|
|||
.sidebar-content a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
font-size: 0.66em;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pagination span {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.th-time {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.results {
|
||||
text-align: left;
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
background-color: #f4f4f4;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.table-results, .filter-results {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.button.active {
|
||||
background-color: lightgray;
|
||||
border: 1px solid gray;
|
||||
border-radius: 4px;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1,3 +0,0 @@
|
|||
.th-time {
|
||||
width: 200px;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/* profile */
|
||||
.scroll-box {
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
background-color: #f8f9fa;
|
||||
white-space: pre-wrap;
|
||||
overflow-y: scroll;
|
||||
resize: none;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
user-select: text;
|
||||
cursor: default;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* avatars */
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover; /* Ensures proper cropping of image */
|
||||
border: 3px solid #ccc;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.avatar-btn {
|
||||
position: absolute;
|
||||
bottom: 10px; /* Adjust this value as needed */
|
||||
/* background: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.avatar-btn-container {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
gap: 10px; /* Space between buttons */
|
||||
}
|
||||
|
||||
.avatar-btn-select,
|
||||
.avatar-btn-remove {
|
||||
/* background: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
.avatar-btn-select {
|
||||
width: 50px;
|
||||
left: -55px;
|
||||
}
|
||||
.avatar-btn-remove {
|
||||
width: 50px;
|
||||
left: 5px;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
Before Width: | Height: | Size: 102 KiB |
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
session_name('jilo');
|
||||
session_start();
|
||||
|
||||
$agent = $_GET['agent'];
|
||||
|
||||
// Check if cached data exists in session
|
||||
if (isset($_SESSION["agent{$agent}_cache"])) {
|
||||
|
||||
// return status, the data, and caching time - in JSON
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $_SESSION["agent{$agent}_cache"],
|
||||
// we store cache time in the session
|
||||
// FIXME may need to move to file cache
|
||||
'cache_time' => $_SESSION["agent{$agent}_cache_time"] ?? time()
|
||||
]);
|
||||
} else {
|
||||
// If no cached data exists
|
||||
echo json_encode(['status' => 'error', 'message' => 'No cached data found']);
|
||||
}
|
||||
|
||||
?>
|
|
@ -3,7 +3,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
var sidebar = document.getElementById('sidebar');
|
||||
var mainContent = document.getElementById('mainContent');
|
||||
var toggleButton = document.getElementById('toggleSidebarButton');
|
||||
var timeNow = document.getElementById('time_now');
|
||||
|
||||
// update localStorage based on the current state
|
||||
function updateStorage() {
|
||||
|
@ -19,13 +18,11 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
toggleButton.textContent = ">>";
|
||||
sidebar.classList.add('collapsed');
|
||||
mainContent.classList.add('expanded');
|
||||
timeNow.style.display = 'none';
|
||||
} else {
|
||||
toggleButton.value = "<<";
|
||||
toggleButton.textContent = "<<";
|
||||
sidebar.classList.remove('collapsed');
|
||||
mainContent.classList.remove('expanded');
|
||||
timeNow.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,11 +38,9 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
if (toggleButton.value === ">>") {
|
||||
toggleButton.value = "<<";
|
||||
toggleButton.textContent = "<<";
|
||||
timeNow.style.display = 'block';
|
||||
} else {
|
||||
toggleButton.value = ">>";
|
||||
toggleButton.textContent = ">>";
|
||||
timeNow.style.display = 'none';
|
||||
}
|
||||
|
||||
// Update with the new state
|
||||
|
|
Loading…
Reference in New Issue