Compare commits
78 Commits
Author | SHA1 | Date |
---|---|---|
|
7d85c9181d | |
|
f88fc0f819 | |
|
54d6ce2ec4 | |
|
0bab284e99 | |
|
cf7d417193 | |
|
1780233778 | |
|
666f3ca98b | |
|
1ba32d86f7 | |
|
d2213ca3e9 | |
|
c83baeee2f | |
|
cd7b78a2e5 | |
|
d854473a06 | |
|
bf197ae96b | |
|
2bbc4af068 | |
|
1cda74cd50 | |
|
3abafe2de7 | |
|
3a5eed933e | |
|
909fbc2626 | |
|
09667920a2 | |
|
ea4b85ddf7 | |
|
8ca9643fc2 | |
|
b02d72b29d | |
|
e84c880289 | |
|
1df19d9609 | |
|
a6cf2fe99b | |
|
f796e100f8 | |
|
8eed6afd46 | |
|
2cdfbe6e86 | |
|
9d3a4557c1 | |
|
acd5ff0a23 | |
|
9a3024cfa6 | |
|
20d9dc0e73 | |
|
8e123cf5f2 | |
|
8765fe22c0 | |
|
e6d6a10795 | |
|
aeb837fee5 | |
|
91aac20998 | |
|
c915bcba9e | |
|
0f868f07e2 | |
|
3943ba49b6 | |
|
8a4816a6ae | |
|
4b783a6b63 | |
|
6191d44944 | |
|
838b8ea9f2 | |
|
15c97859a4 | |
|
6199dad2c6 | |
|
cb040ee408 | |
|
2aaf2ac03f | |
|
27304513d8 | |
|
0cfa9d811e | |
|
54b998a1a8 | |
|
77e674bab5 | |
|
b6fc4a995d | |
|
ca95f3c27e | |
|
22e502c90c | |
|
ae7929b4e1 | |
|
80454de3f2 | |
|
8455a98ec5 | |
|
5d240b1dd8 | |
|
06ffde67f4 | |
|
8bbe4b6274 | |
|
001e6c5be7 | |
|
55b53ef30a | |
|
c011321403 | |
|
42f9738128 | |
|
c0c072884f | |
|
54ddc6577e | |
|
d9aaf97b81 | |
|
f76fd03794 | |
|
3e0729c6cc | |
|
16b7627b60 | |
|
c6e52df33a | |
|
7d459cf508 | |
|
350ba053e8 | |
|
efd7cd74a2 | |
|
c39e53906f | |
|
5463ea0cee | |
|
ba9d14f5d1 |
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -7,16 +7,44 @@ All notable changes to this project will be documented in this file.
|
|||
## Unreleased
|
||||
|
||||
#### Links
|
||||
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.1.1...HEAD
|
||||
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.1.1...HEAD
|
||||
- github: https://github.com/lindeas/jilo-web/compare/v0.1.1...HEAD
|
||||
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.1.1...HEAD
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
## 0.2 - 2024-08-31
|
||||
|
||||
#### Links
|
||||
- upstream: https://code.lindeas.com/lindeas/jilo-web/compare/v0.1.1...v0.2
|
||||
- codeberg: https://codeberg.org/lindeas/jilo-web/compare/v0.1.1...v0.2
|
||||
- github: https://github.com/lindeas/jilo-web/compare/v0.1.1...v0.2
|
||||
- gitlab: https://gitlab.com/lindeas/jilo-web/-/compare/v0.1.1...v0.2
|
||||
|
||||
### Added
|
||||
- Added collapsible front page widgets
|
||||
- Added widgets to conferences, participants and components pages
|
||||
- Added front page widget for monthly conferences and participants number
|
||||
- Added login/registration control and messages
|
||||
- Added default config file locations
|
||||
- Added left collapsible sidebar
|
||||
- Added logo
|
||||
- Added database helper functions
|
||||
- Added support for multiple Jitsi platforms
|
||||
- Added app environments "production" and "development"
|
||||
- Added visualisation of config.js and interface_config.js per Jitsi platform
|
||||
|
||||
### Changed
|
||||
- MVC design - models(classes folder), views(templates folder) and controllers(pages folder)
|
||||
- Changed menus - categories on sidebar menu, jitsi platforms on top menu
|
||||
- Moved all the app code outside of the public web folder
|
||||
- Config file now can have nested arrays
|
||||
|
||||
### Fixed
|
||||
- Fixed SQL when conferences start and end time are not explicitly clear
|
||||
- Web design fixes
|
||||
- Fixed install script
|
||||
|
||||
---
|
||||
|
||||
|
|
25
README.md
25
README.md
|
@ -26,13 +26,15 @@ To see a demo install, go to https://work.lindeas.com/jilo-web-demo/
|
|||
|
||||
## version
|
||||
|
||||
Current version: **0.1.1** released on **2024-07-25**
|
||||
Current version: **0.2** released on **2024-08-31**
|
||||
|
||||
## license
|
||||
|
||||
This project is licensed under the GNU General Public License version 2 (GPL-2.0). See LICENSE file.
|
||||
|
||||
Bootstrap is used in this project and is licensed under the MIT License. See bootstrap-license file
|
||||
Bootstrap is used in this project and is licensed under the MIT License. See license-bootstrap file.
|
||||
|
||||
JQuery is used in this project and is licensed under the MIT License. See license-jquery file.
|
||||
|
||||
## requirements
|
||||
|
||||
|
@ -45,20 +47,29 @@ Bootstrap is used in this project and is licensed under the MIT License. See boo
|
|||
You can install it in the following ways:
|
||||
|
||||
- download the latest release from the **"Releases"** section here
|
||||
```bash
|
||||
tar -xzf jilo-web_*.tgz
|
||||
cd jilo-web/doc/
|
||||
./install.sh
|
||||
```
|
||||
- clone the **git repo**:
|
||||
```bash
|
||||
git clone https://github.com/lindeas/jilo-web.git
|
||||
cd jilo
|
||||
cd jilo-web
|
||||
./install.sh
|
||||
```
|
||||
- DEB and RPM packages are planned, but still unavailable
|
||||
- DEB and RPM packages are planned, but not yet available. There are experimental build scripts in "packaging" folder.
|
||||
|
||||
## config
|
||||
|
||||
- edit index.php and set the system path to the jilo-web.conf.php
|
||||
- edit jilo-web.conf.php and set all the variables correctly
|
||||
- "database" is the sqlite db file for jilo-web itself, create it with `cat jilo-web.schema | sqlite3 jilo-web.db`
|
||||
- "sqlite_file" is the sqlite db file for jilo-web itself, it goes to `app/jilo-web.db`, create it with
|
||||
```bash
|
||||
cd app
|
||||
cat ../doc/jilo-web.schema | sqlite3 jilo-web.db
|
||||
```
|
||||
- "jilo_database" is the sqlite db file for jilo, with data from the Jitsi logs
|
||||
|
||||
## database
|
||||
|
||||
The database is an SQLite file. You also need the sqlite db from jilo (mysql/mariadb support is planned, but still unavailable).
|
||||
The database is an SQLite file. You also need the sqlite db from jilo (mysql/mariadb support is planned, but not yet available).
|
||||
|
|
6
TODO.md
6
TODO.md
|
@ -10,13 +10,13 @@
|
|||
|
||||
- - ~~add bootstrap template~~
|
||||
|
||||
- - clean up the code to follow model-view--controller style
|
||||
- - ~~clean up the code to follow model-view--controller style~~
|
||||
|
||||
- - no HTML inside PHP code
|
||||
- - ~~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
|
||||
- - ~~reduce try/catch usage, use it only for critical errors~~
|
||||
|
||||
- - move all SQL code in the model classes, one query per method
|
||||
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
class Component {
|
||||
private $db;
|
||||
private $queries;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
$this->queries = include('queries.php');
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,11 +19,24 @@ class Component {
|
|||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['jitsi_components'];
|
||||
|
||||
// list of jitsi component events
|
||||
$sql = "
|
||||
SELECT
|
||||
jitsi_component, loglevel, time, component_id, event_type, event_param
|
||||
FROM
|
||||
jitsi_components
|
||||
WHERE
|
||||
jitsi_component = %s
|
||||
AND
|
||||
component_id = %s
|
||||
AND
|
||||
(time >= '%s 00:00:00' AND time <= '%s 23:59:59')
|
||||
ORDER BY
|
||||
time";
|
||||
|
||||
$sql = sprintf($sql, $jitsi_component, $component_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
|
@ -0,0 +1,293 @@
|
|||
<?php
|
||||
|
||||
class Conference {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
|
||||
// search/list specific conference ID
|
||||
public function conferenceById($conference_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// search for a conference by its ID for a time period (if given)
|
||||
$sql = "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
c.conference_id = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
c.conference_id = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
$sql = sprintf($sql, $conference_id, $from_time, $until_time, $conference_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific conference name
|
||||
public function conferenceByName($conference_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// search for a conference by its name for a time period (if given)
|
||||
$sql = "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
c.conference_name = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
c.conference_name = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
$sql = sprintf($sql, $conference_name, $from_time, $until_time, $conference_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// list of all conferences
|
||||
public function conferencesAllFormatted($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// list of conferences for time period (if given)
|
||||
// fields: component, duration, conference ID, conference name, number of participants, name count (the conf name is found), conference host
|
||||
$sql = "
|
||||
SELECT DISTINCT
|
||||
c.jitsi_component,
|
||||
(SELECT COALESCE
|
||||
(
|
||||
(SELECT ce.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,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
(SELECT COUNT(pe.participant_id)
|
||||
FROM participant_events pe
|
||||
WHERE
|
||||
pe.event_type = 'participant joining'
|
||||
AND
|
||||
pe.event_param = c.conference_id) AS participants,
|
||||
name_counts.name_count,
|
||||
c.conference_host
|
||||
FROM
|
||||
conferences c
|
||||
JOIN (
|
||||
SELECT
|
||||
conference_name,
|
||||
COUNT(*) AS name_count
|
||||
FROM
|
||||
conferences
|
||||
GROUP BY
|
||||
conference_name
|
||||
) AS name_counts ON c.conference_name = name_counts.conference_name
|
||||
JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE (ce.time >= '%s 00:00:00' AND ce.time <= '%s 23:59:59')
|
||||
ORDER BY
|
||||
c.id";
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// number of conferences
|
||||
public function conferenceNumber($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// number of conferences for time period (if given)
|
||||
// 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(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_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
|
||||
(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);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
class Config {
|
||||
|
||||
public function getPlatformDetails($config, $platform_id) {
|
||||
$platformDetails = $config['platforms'][$platform_id];
|
||||
return $platformDetails;
|
||||
}
|
||||
|
||||
// loading the config.js
|
||||
public function getPlatformConfigjs($platformDetails, $raw = false) {
|
||||
// constructing the URL
|
||||
$configjsFile = $platformDetails['jitsi_url'] . '/config.js';
|
||||
|
||||
// default content, if we can't get the file contents
|
||||
$platformConfigjs = "The file $configjsFile can't be loaded.";
|
||||
|
||||
// ssl options
|
||||
$contextOptions = [
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_peer_name' => true,
|
||||
],
|
||||
];
|
||||
$context = stream_context_create($contextOptions);
|
||||
|
||||
// get the file
|
||||
$fileContent = @file_get_contents($configjsFile, false, $context);
|
||||
|
||||
if ($fileContent !== false) {
|
||||
|
||||
// when we need only uncommented values
|
||||
if ($raw === false) {
|
||||
// remove block comments
|
||||
$platformConfigjs = preg_replace('!/\*.*?\*/!s', '', $fileContent);
|
||||
// remove single-line comments
|
||||
$platformConfigjs = preg_replace('/\/\/[^\n]*/', '', $platformConfigjs);
|
||||
// remove empty lines
|
||||
$platformConfigjs = preg_replace('/^\s*[\r\n]/m', '', $platformConfigjs);
|
||||
|
||||
// when we need the full file as it is
|
||||
} else {
|
||||
$platformConfigjs = $fileContent;
|
||||
}
|
||||
}
|
||||
|
||||
return $platformConfigjs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// loading the interface_config.js
|
||||
public function getPlatformInterfaceConfigjs($platformDetails, $raw = false) {
|
||||
// constructing the URL
|
||||
$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.";
|
||||
|
||||
// ssl options
|
||||
$contextOptions = [
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_peer_name' => true,
|
||||
],
|
||||
];
|
||||
$context = stream_context_create($contextOptions);
|
||||
|
||||
// get the file
|
||||
$fileContent = @file_get_contents($interfaceConfigjsFile, false, $context);
|
||||
|
||||
if ($fileContent !== false) {
|
||||
|
||||
// when we need only uncommented values
|
||||
if ($raw === false) {
|
||||
// remove block comments
|
||||
$platformInterfaceConfigjs = preg_replace('!/\*.*?\*/!s', '', $fileContent);
|
||||
// remove single-line comments
|
||||
$platformInterfaceConfigjs = preg_replace('/\/\/[^\n]*/', '', $platformInterfaceConfigjs);
|
||||
// remove empty lines
|
||||
$platformInterfaceConfigjs = preg_replace('/^\s*[\r\n]/m', '', $platformInterfaceConfigjs);
|
||||
|
||||
// when we need the full file as it is
|
||||
} else {
|
||||
$platformInterfaceConfigjs = $fileContent;
|
||||
}
|
||||
}
|
||||
|
||||
return $platformInterfaceConfigjs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
require '../app/helpers/errors.php';
|
||||
|
||||
class Database {
|
||||
private $pdo;
|
||||
|
||||
public function __construct($options) {
|
||||
// pdo needed
|
||||
if ( !extension_loaded('pdo') ) {
|
||||
$error = getError('PDO extension not loaded.');
|
||||
}
|
||||
|
||||
// options check
|
||||
if (empty($options['type'])) {
|
||||
$error = getError('Database type is not set.');
|
||||
}
|
||||
|
||||
// database type
|
||||
switch ($options['type']) {
|
||||
case 'sqlite':
|
||||
$this->connectSqlite($options);
|
||||
break;
|
||||
case 'mysql' || 'mariadb':
|
||||
$this->connectMysql($options);
|
||||
break;
|
||||
default:
|
||||
$error = getError("Database type \"{$options['type']}\" is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private function connectSqlite($options) {
|
||||
// pdo_sqlite extension is needed
|
||||
if (!extension_loaded('pdo_sqlite')) {
|
||||
$error = getError('PDO extension for SQLite not loaded.');
|
||||
}
|
||||
|
||||
// SQLite options
|
||||
if (empty($options['dbFile']) || !file_exists($options['dbFile'])) {
|
||||
$error = getError("SQLite database file \"{$dbFile}\" not found.");
|
||||
}
|
||||
|
||||
// connect to SQLite
|
||||
try {
|
||||
$this->pdo = new PDO("sqlite:" . $options['dbFile']);
|
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException $e) {
|
||||
$error = getError('SQLite connection failed: ', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function connectMysql($options) {
|
||||
// pdo_mysql extension is needed
|
||||
if (!extension_loaded('pdo_mysql')) {
|
||||
$error = getError('PDO extension for MySQL not loaded.');
|
||||
}
|
||||
|
||||
// MySQL options
|
||||
if (empty($options['host']) || empty($options['dbname']) || empty($options['user'])) {
|
||||
$error = getError('MySQL connection data is missing.');
|
||||
}
|
||||
|
||||
// Connect to MySQL
|
||||
try {
|
||||
$dsn = "mysql:host={$options['host']};port={$options['port']};dbname={$options['dbname']};charset=utf8";
|
||||
$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: ', $config['environment'], $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getConnection() {
|
||||
return $this->pdo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
class Participant {
|
||||
private $db;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant ID
|
||||
public function conferenceByParticipantId($participant_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// list conferences where participant ID (endpoint_id) is found
|
||||
$sql = "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
p.endpoint_id = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
participant_id = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
$sql = sprintf($sql, $participant_id, $from_time, $until_time, $participant_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant name (stats_id)
|
||||
public function conferenceByParticipantName($participant_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// list conferences where participant name (stats_id) is found
|
||||
$sql = "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.event_type = 'stats_id' AND pe.event_param LIKE '%%%s%%'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
event_type = 'stats_id' AND event_param LIKE '%%%s%%'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
$sql = sprintf($sql, $participant_name, $from_time, $until_time, $participant_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant IP
|
||||
public function conferenceByParticipantIP($participant_ip, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// list conferences where participant IP is found
|
||||
$sql = "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.event_type = 'pair selected' AND pe.event_param = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
event_type = 'pair selected' AND event_param = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time";
|
||||
|
||||
$sql = sprintf($sql, $participant_ip, $from_time, $until_time, $participant_ip, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// list of all participants
|
||||
public function participantsAll($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// list all participants
|
||||
$sql = "
|
||||
SELECT DISTINCT
|
||||
p.jitsi_component, p.endpoint_id, p.conference_id
|
||||
FROM
|
||||
participants p
|
||||
JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59'
|
||||
ORDER BY p.id";
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// number of participants
|
||||
public function participantNumber($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
|
||||
// number of participants for time period (if given)
|
||||
$sql = "
|
||||
SELECT COUNT(DISTINCT p.endpoint_id) as participants
|
||||
FROM
|
||||
participants p
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
(pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
AND pe.event_type = 'participant joining'";
|
||||
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
class Router {
|
||||
|
||||
private $routes = [];
|
||||
|
||||
public function add() {
|
||||
$this->routes[$pattern] = $callback;
|
||||
}
|
||||
|
||||
public function dispatch($url) {
|
||||
// remove variables from url
|
||||
$url = strtok($url, '?');
|
||||
|
||||
foreach ($this->routes as $pattern => $callback) {
|
||||
if (preg_match('#^' . $pattern . '$#', $url, $matches)) {
|
||||
// move any exact match
|
||||
array_shift($matches);
|
||||
return $this->invoke($callback, $matches);
|
||||
}
|
||||
}
|
||||
|
||||
// if there was no match at all, return 404
|
||||
http_response_code(404);
|
||||
echo '404 page not found';
|
||||
}
|
||||
|
||||
private function invoke($callback, $params) {
|
||||
list($controllerName, $methodName) = explode('@', $callback);
|
||||
// $controllerClass = "\\App\\Controllers\\$controllerName";
|
||||
$controllerClass = "../pages/$pageName";
|
||||
$controller = new $controllerClass();
|
||||
call_user_func_array([$controller, $methodName], $params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
//*******************
|
||||
// edit to customize
|
||||
//*******************
|
||||
|
||||
// domain for the web app
|
||||
'domain' => 'localhost',
|
||||
// subfolder for the web app, if any
|
||||
'folder' => '/jilo-web/',
|
||||
// set to false to disable new registrations
|
||||
'registration_enabled' => true,
|
||||
// will be displayed on login screen
|
||||
'login_message' => '',
|
||||
|
||||
//*******************************************
|
||||
// edit only if needed for tests or debugging
|
||||
//*******************************************
|
||||
|
||||
// database
|
||||
'db' => [
|
||||
// DB type for the web app, currently only "sqlite" is used
|
||||
'db_type' => 'sqlite',
|
||||
// default is ../app/jilo-web.db
|
||||
'sqlite_file' => '../app/jilo-web.db',
|
||||
],
|
||||
// system info
|
||||
'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;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
// connect to database
|
||||
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 \"{$platform_id}\", database file \"{$dbFile}\"not found."));
|
||||
}
|
||||
$db = new Database([
|
||||
'type' => 'sqlite',
|
||||
'dbFile' => $dbFile,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
$error = getError('Error connecting to DB.', $e->getMessage());
|
||||
include '../app/templates/block-message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// connecting to a jilo-web database of the web app
|
||||
} else {
|
||||
|
||||
// sqlite database file
|
||||
if ($config['db']['db_type'] === 'sqlite') {
|
||||
try {
|
||||
$db = new Database([
|
||||
'type' => $config['db']['db_type'],
|
||||
'dbFile' => $config['db']['sqlite_file'],
|
||||
]);
|
||||
$pdo = $db->getConnection();
|
||||
} catch (Exception $e) {
|
||||
$error = getError('Error connecting to DB.', $e->getMessage());
|
||||
include '../app/templates/block-message.php';
|
||||
exit();
|
||||
}
|
||||
// mysql/mariadb database
|
||||
} elseif ($config['db']['db_type'] === 'mysql' || $config['db']['db_type'] === 'mariadb') {
|
||||
try {
|
||||
$db = new Database([
|
||||
'type' => $config['db']['db_type'],
|
||||
'host' => $config['db']['sql_host'] ?? 'localhost',
|
||||
'port' => $config['db']['sql_port'] ?? '3306',
|
||||
'dbname' => $config['db']['sql_database'],
|
||||
'user' => $config['db']['sql_username'],
|
||||
'password' => $config['db']['sql_password'],
|
||||
]);
|
||||
$pdo = $db->getConnection();
|
||||
} catch (Exception $e) {
|
||||
$error = getError('Error connecting to DB.', $e->getMessage());
|
||||
include '../app/templates/block-message.php';
|
||||
exit();
|
||||
}
|
||||
// unknown database
|
||||
} else {
|
||||
$error = "Error: unknow database type \"{$config['db']['db_type']}\"";
|
||||
include '../app/templates/block-message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $db;
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
function getError($message, $error = '', $environment = null) {
|
||||
global $config;
|
||||
$environment = $config['environment'] ?? 'production';
|
||||
|
||||
if ($environment === 'production') {
|
||||
return 'There was an unexpected error. Please try again.';
|
||||
} else {
|
||||
return $error ?: $message;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
// render config variables array
|
||||
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) {
|
||||
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;
|
||||
if ($parent === 'platforms') {
|
||||
$indent = 100;
|
||||
}
|
||||
if ($config_item === 'platforms') {
|
||||
renderConfig($config_value, $indent, $platform, 'platforms');
|
||||
} else {
|
||||
renderConfig($config_value, $indent, $platform);
|
||||
}
|
||||
$indent = 0;
|
||||
} else {
|
||||
// if it's not array, just display it
|
||||
?>
|
||||
<div class="border col-md-8 text-start">
|
||||
<?= htmlspecialchars($config_value ?? '')?>
|
||||
<?= $platform ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
$time_range_specified = false;
|
||||
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($_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;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/component.php';
|
||||
|
||||
// connect to database
|
||||
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 (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';
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Component events listings
|
||||
//
|
||||
|
||||
|
||||
// list of all component events (default)
|
||||
$component = new Component($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $component->jitsiComponents($jitsi_component, $component_id, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$components = array();
|
||||
$components['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$component_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'loglevel' => $loglevel,
|
||||
'time' => $time,
|
||||
'component ID' => $component_id,
|
||||
'event' => $event_type,
|
||||
'param' => $event_param,
|
||||
);
|
||||
// populate the result array
|
||||
array_push($components['records'], $component_record);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'AllComponents';
|
||||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
$widget['title'] = 'Jitsi events for component <strong>' . $_REQUEST['name'] . '</strong>';
|
||||
} elseif (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$widget['title'] = 'Jitsi events for component ID <strong>' . $_REQUEST['id'] . '</strong>';
|
||||
} else {
|
||||
$widget['title'] = 'Jitsi events for <strong>all components</strong>';
|
||||
}
|
||||
// widget records
|
||||
if (!empty($components['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($components['records'][0]);
|
||||
$widget['table_records'] = $components['records'];
|
||||
}
|
||||
|
||||
// display the widget
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/conference.php';
|
||||
|
||||
// connect to database
|
||||
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 (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$conferenceId = $_REQUEST['id'];
|
||||
unset($_REQUEST['name']);
|
||||
unset($conferenceName);
|
||||
} elseif (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
unset($conferenceId);
|
||||
$conferenceName = $_REQUEST['name'];
|
||||
} else {
|
||||
unset($conferenceId);
|
||||
unset($conferenceName);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Conference listings
|
||||
//
|
||||
|
||||
|
||||
$conference = new Conference($db);
|
||||
|
||||
// search and list specific conference ID
|
||||
if (isset($conferenceId)) {
|
||||
$search = $conference->conferenceById($conferenceId, $from_time, $until_time);
|
||||
// search and list specific conference name
|
||||
} elseif (isset($conferenceName)) {
|
||||
$search = $conference->conferenceByName($conferenceName, $from_time, $until_time);
|
||||
// list of all conferences (default)
|
||||
} else {
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
|
||||
// search and list specific conference ID
|
||||
if (isset($conferenceId)) {
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// search and list specific conference name
|
||||
} elseif (isset($conferenceName)) {
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// list of all conferences (default)
|
||||
} else {
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
}
|
||||
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'Conferences';
|
||||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
$widget['title'] = 'Conferences with name matching "<strong>' . $_REQUEST['name'] . '"</strong>';
|
||||
} elseif (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$widget['title'] = 'Conference with ID "<strong>' . $_REQUEST['id'] . '"</strong>';
|
||||
} else {
|
||||
$widget['title'] = 'All conferences';
|
||||
}
|
||||
// widget records
|
||||
if (!empty($conferences['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($conferences['records'][0]);
|
||||
$widget['table_records'] = $conferences['records'];
|
||||
}
|
||||
|
||||
// display the widget
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
$action = $_REQUEST['action'] ?? '';
|
||||
require_once '../app/classes/config.php';
|
||||
require '../app/helpers/errors.php';
|
||||
require '../app/helpers/config.php';
|
||||
|
||||
$configure = new Config();
|
||||
|
||||
// if a form is submitted, it's from the edit page
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
// load the config file and initialize a copy
|
||||
$content = file_get_contents($config_file);
|
||||
$updatedContent = $content;
|
||||
|
||||
// new platform adding
|
||||
if (isset($_POST['new']) && $_POST['new'] === 'true') {
|
||||
$newPlatform = [
|
||||
'name' => $_POST['name'],
|
||||
'jitsi_url' => $_POST['jitsi_url'],
|
||||
'jilo_database' => $_POST['jilo_database'],
|
||||
];
|
||||
|
||||
// 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'];
|
||||
|
||||
$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'];
|
||||
|
||||
$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
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
header("Location: $app_root?platform=$platform_id&page=config");
|
||||
exit();
|
||||
|
||||
// no form submitted, show the templates
|
||||
} else {
|
||||
|
||||
// $item - config.js and interface_config.js are special case; remote loaded files
|
||||
switch ($item) {
|
||||
case 'configjs':
|
||||
$mode = $_REQUEST['mode'] ?? '';
|
||||
$raw = ($mode === 'raw');
|
||||
$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');
|
||||
$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 file
|
||||
default:
|
||||
switch ($action) {
|
||||
case 'add':
|
||||
include('../app/templates/config-add-platform.php');
|
||||
break;
|
||||
case 'edit':
|
||||
include('../app/templates/config-edit-platform.php');
|
||||
break;
|
||||
case 'delete':
|
||||
include('../app/templates/config-delete-platform.php');
|
||||
break;
|
||||
default:
|
||||
include('../app/templates/config-list.php');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/conference.php';
|
||||
require '../app/classes/participant.php';
|
||||
|
||||
// connect to database
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
|
||||
//
|
||||
// dashboard widget listings
|
||||
//
|
||||
|
||||
|
||||
////
|
||||
// monthly usage
|
||||
$conference = new Conference($db);
|
||||
$participant = new Participant($db);
|
||||
|
||||
// monthly conferences for the last year
|
||||
$fromMonth = (new DateTime())->sub(new DateInterval('P1Y'));
|
||||
$fromMonth->modify('first day of this month');
|
||||
$thisMonth = new DateTime();
|
||||
$from_time = $fromMonth->format('Y-m-d');
|
||||
$until_time = $thisMonth->format('Y-m-d');
|
||||
|
||||
$widget['records'] = array();
|
||||
|
||||
// loop 1 year in the past
|
||||
$i = 0;
|
||||
while ($fromMonth < $thisMonth) {
|
||||
|
||||
$untilMonth = clone $fromMonth;
|
||||
$untilMonth->modify('last day of this month');
|
||||
|
||||
$from_time = $fromMonth->format('Y-m-d');
|
||||
$until_time = $untilMonth->format('Y-m-d');
|
||||
|
||||
$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');
|
||||
|
||||
// populate the records
|
||||
$widget['records'][$i] = array(
|
||||
'from_time' => $from_time,
|
||||
'until_time' => $until_time,
|
||||
'table_headers' => $month,
|
||||
'conferences' => $searchConferenceNumber[0]['conferences'],
|
||||
'participants' => $searchParticipantNumber[0]['participants'],
|
||||
);
|
||||
|
||||
// move everything one month in future
|
||||
$untilMonth->add(new DateInterval('P1M'));
|
||||
$fromMonth->add(new DateInterval('P1M'));
|
||||
$i++;
|
||||
}
|
||||
|
||||
$time_range_specified = true;
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'LastYearMonths';
|
||||
$widget['title'] = 'Conferences monthly stats for the last year';
|
||||
$widget['collapsible'] = true;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = false;
|
||||
if (!empty($searchConferenceNumber) && !empty($searchParticipantNumber)) {
|
||||
$widget['full'] = true;
|
||||
}
|
||||
|
||||
// display the widget
|
||||
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);
|
||||
$until_time = date('Y-m-d', time());
|
||||
$time_range_specified = true;
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'LastDays';
|
||||
$widget['title'] = 'Conferences for the last 2 days';
|
||||
$widget['collapsible'] = true;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = false;
|
||||
if (!empty($conferences['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($conferences['records'][0]);
|
||||
$widget['table_records'] = $conferences['records'];
|
||||
}
|
||||
|
||||
// display the widget
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
|
||||
////
|
||||
// last 10 conferences
|
||||
$conference = new Conference($db);
|
||||
|
||||
// all time
|
||||
$from_time = '0000-01-01';
|
||||
$until_time = '9999-12-31';
|
||||
$time_range_specified = false;
|
||||
// number of conferences to show
|
||||
$conference_number = 10;
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
$i = 0;
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
|
||||
// we only take the first 10 results
|
||||
$i++;
|
||||
if ($i == 10) break;
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'LastConferences';
|
||||
$widget['title'] = 'The last ' . $conference_number . ' conferences';
|
||||
$widget['collapsible'] = true;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = false;
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($conferences['records'][0]);
|
||||
$widget['table_records'] = $conferences['records'];
|
||||
}
|
||||
|
||||
// display the widget
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
|
@ -1,13 +1,17 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/user.php';
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/user.php';
|
||||
|
||||
// clear the global error var before login
|
||||
unset($error);
|
||||
|
||||
try {
|
||||
$db = new Database($config['database']);
|
||||
|
||||
// connect to database
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config);
|
||||
|
||||
$user = new User($db);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
|
@ -31,18 +35,6 @@ try {
|
|||
}
|
||||
|
||||
// set session lifetime and cookies
|
||||
// FIXME: need to set this before session start (otherwise we need the separate cookie)
|
||||
// ini_set('session.gc_maxlifetime', $gc_maxlifetime);
|
||||
// session_set_cookie_params([
|
||||
// 'lifetime' => $setcookie_lifetime,
|
||||
// 'samesite' => 'Strict',
|
||||
// 'httponly' => true,
|
||||
// 'secure' => isset($_SERVER['HTTPS']),
|
||||
// 'domain' => $config['domain'],
|
||||
// 'path' => $config['folder']
|
||||
// ]);
|
||||
// session_start();
|
||||
// FIXME we use separate cookie, because the above won't work
|
||||
setcookie('username', $username, [
|
||||
'expires' => $setcookie_lifetime,
|
||||
'path' => $config['folder'],
|
||||
|
@ -65,9 +57,14 @@ try {
|
|||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
$error = getError('There was an unexpected error. Please try again.', $e->getMessage());
|
||||
}
|
||||
|
||||
include 'templates/form-login.php';
|
||||
if (!empty($config['login_message'])) {
|
||||
$notice = $config['login_message'];
|
||||
include '../app/templates/block-message.php';
|
||||
}
|
||||
|
||||
include '../app/templates/form-login.php';
|
||||
|
||||
?>
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/participant.php';
|
||||
|
||||
// connect to database
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config, 'jilo', $platform_id);
|
||||
|
||||
// specify time range
|
||||
include '../app/helpers/time_range.php';
|
||||
|
||||
// participant id/name/IP are specified when searching specific participant(s)
|
||||
// participant name - this is 'stats_id' in the db
|
||||
// either id, name, OR IP - in that order
|
||||
// we use $_REQUEST, so that both links and forms work
|
||||
if (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$participantId = $_REQUEST['id'];
|
||||
unset($_REQUEST['name']);
|
||||
unset($participantName);
|
||||
} elseif (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
unset($participantId);
|
||||
$participantName = $_REQUEST['name'];
|
||||
} elseif (isset($_REQUEST['ip']) && $_REQUEST['ip'] != '') {
|
||||
unset($participantId);
|
||||
$participantIp = $_REQUEST['ip'];
|
||||
} else {
|
||||
unset($participantId);
|
||||
unset($participantName);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Participant listings
|
||||
//
|
||||
|
||||
$participant = new Participant($db);
|
||||
|
||||
// search and list specific participant ID
|
||||
if (isset($participantId)) {
|
||||
$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 = $participant->conferenceByParticipantName($participantName, $from_time, $until_time);
|
||||
// search and list specific participant IP
|
||||
} elseif (isset($participantIp)) {
|
||||
$search = $participant->conferenceByParticipantIP($participantIp, $from_time, $until_time);
|
||||
// list of all participants (default)
|
||||
} else {
|
||||
// prepare the result
|
||||
$search = $participant->participantsAll($from_time, $until_time);
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
$participants = array();
|
||||
$participants['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// search and list specific participant ID
|
||||
if (isset($participantId)) {
|
||||
$participant_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// search and list specific participant name (stats_id)
|
||||
} elseif (isset($participantName)) {
|
||||
$participant_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// search and list specific participant IP
|
||||
} elseif (isset($participantIp)) {
|
||||
$participant_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// list of all participants (default)
|
||||
} else {
|
||||
$participant_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'participant ID' => $endpoint_id,
|
||||
'conference ID' => $conference_id
|
||||
);
|
||||
}
|
||||
|
||||
// populate the result array
|
||||
array_push($participants['records'], $participant_record);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the widget
|
||||
$widget['full'] = false;
|
||||
$widget['name'] = 'Participants';
|
||||
$widget['collapsible'] = false;
|
||||
$widget['collapsed'] = false;
|
||||
$widget['filter'] = true;
|
||||
|
||||
// widget title
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
$widget['title'] = 'Conferences with participant name (stats_id) matching "<strong>' . $_REQUEST['name'] . '"</strong>';
|
||||
} elseif (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$widget['title'] = 'Conference with participant ID matching "<strong>' . $_REQUEST['id'] . '"</strong>';
|
||||
} elseif (isset($participantIp)) {
|
||||
$widget['title'] = 'Conference with participant IP matching "<strong>' . $participantIp . '"</strong>';
|
||||
} else {
|
||||
$widget['title'] = 'All participants';
|
||||
}
|
||||
// widget records
|
||||
if (!empty($participants['records'])) {
|
||||
$widget['full'] = true;
|
||||
$widget['table_headers'] = array_keys($participants['records'][0]);
|
||||
$widget['table_records'] = $participants['records'];
|
||||
}
|
||||
|
||||
// display the widget
|
||||
include('../app/templates/widget.php');
|
||||
|
||||
?>
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
include('../app/templates/widget-profile.php');
|
||||
|
||||
?>
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
// registration is allowed, go on
|
||||
if ($config['registration_enabled'] === true) {
|
||||
|
||||
require_once '../app/classes/database.php';
|
||||
require '../app/classes/user.php';
|
||||
unset($error);
|
||||
|
||||
try {
|
||||
|
||||
// connect to database
|
||||
require '../app/helpers/database.php';
|
||||
$db = connectDB($config);
|
||||
|
||||
$user = new User($db);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
|
||||
// redirect to login
|
||||
if ( $user->register($username, $password) ) {
|
||||
$_SESSION['notice'] = "Registration successful.<br />You can log in now.";
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
// registration fail, redirect to login
|
||||
} else {
|
||||
$_SESSION['error'] = "Registration failed.";
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = getError('There was an unexpected error. Please try again.', $e->getMessage());
|
||||
}
|
||||
|
||||
include '../app/templates/block-message.php';
|
||||
include '../app/templates/form-register.php';
|
||||
|
||||
// registration disabled
|
||||
} else {
|
||||
$notice = 'Registration is disabled';
|
||||
include '../app/templates/block-message.php';
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,7 @@
|
|||
<?php if (isset($error)) { ?>
|
||||
<div class="error"><?php echo $error; ?></div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (isset($notice)) { ?>
|
||||
<div class="notice"><?php echo $notice; ?></div>
|
||||
<?php } ?>
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
<!-- 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" 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=\"" . $_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=\"" . $_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=\"" . $_REQUEST['ip'] . "\"" ?> maxlength="15" size="15" />
|
||||
<?php } ?>
|
||||
<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 -->
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<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="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config">
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="name" class="form-label">name</label>
|
||||
<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 />
|
||||
<p class="text-start"><small>descriptive name for the platform</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="jitsi_url" class="form-label">Jitsi URL</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="jitsi_url" value="https://" required />
|
||||
<p class="text-start"><small>URL of the Jitsi Meet (used for checks and for loading config.js)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="jilo_database" class="form-label">jilo_database</label>
|
||||
<span class="text-danger" style="margin-right: -12px;">*</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input class="form-control" type="text" name="jilo_database" value="" required />
|
||||
<p class="text-start"><small>path to the database file (relative to the app root)</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="new" value="true" />
|
||||
|
||||
<br />
|
||||
<a class="btn btn-secondary" href="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<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="<?= $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($config_item) ?>:</label>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="text-start"><?= htmlspecialchars($config_value ?? '')?></div>
|
||||
<input type="hidden" name="<?= htmlspecialchars($config_item) ?>" value="<?= htmlspecialchars($config_value ?? '')?>" />
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<br />
|
||||
<input type="hidden" name="platform" value="<?= htmlspecialchars($platform_id) ?>" />
|
||||
<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="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-danger" value="Delete" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<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="<?= $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($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($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 ($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 ($config_item === 'jilo_database') { ?>
|
||||
<p class="text-start"><small>path to the database file (relative to the app root)</small></p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<br />
|
||||
<input type="hidden" name="platform" value="<?= htmlspecialchars($platform_id) ?>" />
|
||||
<a class="btn btn-secondary" href="<?= $app_root ?>?page=config" />Cancel</a>
|
||||
<input type="submit" class="btn btn-primary" value="Save" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<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['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="<?= $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="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=configjs&mode=raw">view raw file contents</a></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<pre style="text-align: left;">
|
||||
<?php
|
||||
echo htmlspecialchars($platformConfigjs);
|
||||
?>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<div class="card text-center w-75 mx-lef">
|
||||
<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['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="<?= $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="<?= $app_root ?>?platform=<?= htmlspecialchars($platform_id) ?>&page=config&item=interfaceconfigjs&mode=raw">view raw file contents</a></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
<pre style="text-align: left;">
|
||||
<?php
|
||||
echo htmlspecialchars($platformInterfaceConfigjs);
|
||||
?>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
<!-- widget "config" -->
|
||||
<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">platform variables</p>
|
||||
<?php
|
||||
include '../app/helpers/render.php';
|
||||
renderConfig($config, '0');
|
||||
echo "\n";
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "config" -->
|
|
@ -0,0 +1,20 @@
|
|||
<!-- login form -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<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="<?= $app_root ?>?page=login">
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<br />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<br />
|
||||
<label for="remember_me">
|
||||
<input type="checkbox" id="remember_me" name="remember_me" />
|
||||
remember me
|
||||
</label>
|
||||
<br /> <br />
|
||||
<input type="submit" class="btn btn-primary" value="Login" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /login form -->
|
|
@ -0,0 +1,15 @@
|
|||
<!-- registration form -->
|
||||
<div class="card text-center w-50 mx-auto">
|
||||
<h2 class="card-header">Register</h2>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Enter credentials for registration:</p>
|
||||
<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 />
|
||||
<input type="submit" class="btn btn-primary" value="Register" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /registration form -->
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
<?php if ($page !== 'login' && $page !== 'register') { ?>
|
||||
<!-- /Main content -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php } ?>
|
||||
<!-- Footer -->
|
||||
<div id="footer">Jilo Web <?= $config['version'] ?> ©2024 - web interface for <a href="https://lindeas.com/jilo">Jilo</a></div>
|
||||
<!-- /Footer -->
|
||||
|
||||
</div>
|
||||
|
||||
<script src="static/sidebar.js"></script>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -2,12 +2,21 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="static/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="static/all.css">
|
||||
<script src="static/bootstrap.min.js"></script>
|
||||
<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>
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
|
||||
<script>
|
||||
// restore sidebar state before the page is rendered
|
||||
(function () {
|
||||
var savedState = localStorage.getItem('sidebarState');
|
||||
if (savedState === 'collapsed') {
|
||||
document.documentElement.classList.add('sidebar-collapsed');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<title>Jilo Web</title>
|
||||
</head>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
<!-- Menu -->
|
||||
<div class="menu-container">
|
||||
<ul class="menu-left">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<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 <?php echo $config['version']; ?></li>
|
||||
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
|
||||
<?php foreach ($config['platforms'] as $index => $platform) { ?>
|
||||
<li style="margin-right: 3px;">
|
||||
<a style="background-color: #111;" href="?platform=<?= htmlspecialchars($index) ?>&page=front">
|
||||
<?= htmlspecialchars($platform['name']) ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-right">
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
<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="<?= $app_root ?>?page=login">login</a></li>
|
||||
<li><a href="<?= $app_root ?>?page=register">register</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /Menu -->
|
|
@ -0,0 +1,63 @@
|
|||
<div class="row">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-md-3 sidebar-wrapper bg-light" id="sidebar">
|
||||
<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">
|
||||
|
||||
<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>
|
||||
<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="<?= $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="<?= $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>jilo-web config</small></p></li>
|
||||
|
||||
<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>
|
||||
<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-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>
|
||||
<!-- /Sidebar -->
|
||||
|
||||
<!-- Main content -->
|
||||
<div class="col-md-9 main-content" id="mainContent">
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
<div class="row">
|
||||
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
<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'); } ?>
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= $widget['name']; ?>" -->
|
||||
<div class="collapse show" id="collapse<?= $widget['name'] ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<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-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="<?= $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 } ?>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>participants</td>
|
||||
<?php foreach ($widget['records'] as $record) { ?>
|
||||
<td><?php if (!empty($record['participants'])) { ?>
|
||||
<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 } ?>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /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" -->
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
<div class="row">
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
<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'); } ?>
|
||||
<?php if ($widget['collapsible'] === true) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<!-- widget "<?= $widget['name']; ?>" -->
|
||||
<div class="collapse show" id="collapse<?= $widget['name'] ?>">
|
||||
<?php if ($time_range_specified) { ?>
|
||||
<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-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="<?= $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="<?= $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="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&id=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'component ID') { ?>
|
||||
<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="<?= $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="<?= $app_root ?>?platform=<?= $platform_id?>&page=participants&ip=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } elseif ($key === 'component') { ?>
|
||||
<td><a href="<?= $app_root ?>?platform=<?= $platform_id?>&page=components&name=<?= htmlspecialchars($column ?? '') ?>"><?= htmlspecialchars($column ?? '') ?></a></td>
|
||||
<?php } else { ?>
|
||||
<td><?= htmlspecialchars($column ?? '') ?></td>
|
||||
<?php }
|
||||
} ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php } else { ?>
|
||||
<p class="m-3">No matching records found.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /widget "<?= $widget['name']; ?>" -->
|
15
config.nginx
15
config.nginx
|
@ -1,15 +0,0 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name $DOMAIN;
|
||||
|
||||
root $INSTALL_DIR;
|
||||
index index.php;
|
||||
|
||||
location / {
|
||||
try_files \$uri \$uri/ /index.php?\$args;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
RewriteEngine On
|
||||
|
||||
# limit access to .htaccess
|
||||
<Files .htaccess>
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# don't rewrite CSS, JS, etc.
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
|
||||
# all other go to index.php
|
||||
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
|
|
@ -4,4 +4,9 @@
|
|||
|
||||
CustomLog \${APACHE_LOG_DIR}/jilo-web_access.log combined
|
||||
ErrorLog \${APACHE_LOG_DIR}/jilo-web_error.log
|
||||
|
||||
<Directory $INSTALL_DIR>
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
</VirtualHost>
|
|
@ -0,0 +1,22 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name $DOMAIN;
|
||||
|
||||
root $INSTALL_DIR;
|
||||
index index.php;
|
||||
|
||||
location / {
|
||||
try_files \$uri \$uri/ /index.php?\$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/run/php/php-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ if [ "$EUID" -ne 0 ] && [ -z "$SUDO_USER" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=`grep version jilo-web.conf.php | cut -d "'" -f 4`
|
||||
VERSION=`grep version ../app/config/jilo-web.conf.php | cut -d "'" -f 4`
|
||||
|
||||
# main install function
|
||||
function install() {
|
||||
|
@ -20,23 +20,24 @@ function install() {
|
|||
WEB_DIR=${WEB_DIR:-jilo-web}
|
||||
|
||||
INSTALL_DIR="/opt/jilo-web/public_html"
|
||||
APP_DIR="/opt/jilo-web/app"
|
||||
DOC_DIR="/opt/jilo-web/doc"
|
||||
ETC_DIR="/opt/jilo-web/etc"
|
||||
|
||||
mkdir -p $INSTALL_DIR
|
||||
cp -r ./public_html/* $INSTALL_DIR
|
||||
cp -r ../public_html/* $INSTALL_DIR
|
||||
|
||||
mkdir -p $DOC_DIR
|
||||
cp CHANGELOG.md $DOC_DIR
|
||||
cp LICENSE $DOC_DIR
|
||||
cp README.md $DOC_DIR
|
||||
cp TODO.md $DOC_DIR
|
||||
cp config.apache $DOC_DIR
|
||||
cp config.nginx $DOC_DIR
|
||||
cp ../CHANGELOG.md $DOC_DIR
|
||||
cp ../LICENSE $DOC_DIR
|
||||
cp ../README.md $DOC_DIR
|
||||
cp ../TODO.md $DOC_DIR
|
||||
cp ../license-bootstrap $DOC_DIR
|
||||
cp ../license-jquery $DOC_DIR
|
||||
cp -r ../doc/ $DOC_DIR
|
||||
|
||||
mkdir -p $ETC_DIR
|
||||
cp jilo-web.conf.php $ETC_DIR
|
||||
cp jilo-web.schema $ETC_DIR
|
||||
cp ../app/config/jilo-web.conf.php $ETC_DIR
|
||||
|
||||
#FIXME
|
||||
#mkdir -p "jilo-web-$VERSION/usr/share/man/man8"
|
|
@ -1,5 +1,5 @@
|
|||
Package: jilo-web
|
||||
Version: 0.1.1
|
||||
Version: 0.2
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: all
|
|
@ -1,4 +1,4 @@
|
|||
.TH JILO-WEB "8" "July 2024" "jilo-web 0.1.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.1.1
|
||||
0.2
|
||||
|
||||
.SH SEE ALSO
|
||||
jilo(8), jilo-cli(8)
|
|
@ -1,5 +1,5 @@
|
|||
Name: jilo-web
|
||||
Version: 0.1.1
|
||||
Version: 0.2
|
||||
Release: 1%{?dist}
|
||||
Summary: Jitsi logs web observer
|
||||
|
||||
|
@ -54,6 +54,8 @@ cp %{sourcedir}/man-jilo.8 %{buildroot}/usr/share/man/man8/%{name}.8
|
|||
/usr/share/man/man8/%{name}.8.gz
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
- Build of upstream v0.1.1
|
||||
* Wed Jul 12 2024 Yasen Pramatarov <yasen@lindeas.com> 0.1
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
$config = [
|
||||
'domain' => 'localhost',
|
||||
'folder' => '/jilo-web/',
|
||||
'database' => '/home/yasen/work/code/git/lindeas-code/jilo-web/jilo-web.db',
|
||||
'jilo_database' => '/home/yasen/work/code/git/lindeas-code/jilo/jilo.db',
|
||||
'version' => '0.1.1',
|
||||
];
|
||||
|
||||
?>
|
|
@ -0,0 +1,20 @@
|
|||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
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.
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Conference {
|
||||
private $db;
|
||||
private $queries;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
$this->queries = include('queries.php');
|
||||
}
|
||||
|
||||
|
||||
// search/list specific conference ID
|
||||
public function conferenceById($conference_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['conference_by_id'];
|
||||
$sql = sprintf($sql, $conference_id, $from_time, $until_time, $conference_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific conference name
|
||||
public function conferenceByName($conference_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['conference_by_name'];
|
||||
$sql = sprintf($sql, $conference_name, $from_time, $until_time, $conference_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// list of all conferences
|
||||
public function conferencesAllFormatted($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['conferences_all_formatted'];
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Database {
|
||||
private $pdo;
|
||||
|
||||
public function __construct($dbFile) {
|
||||
|
||||
// pdo and pdo_sqlite needed
|
||||
if ( !extension_loaded('pdo_sqlite') ) {
|
||||
throw new Exception('PDO extension for SQLite not loaded.');
|
||||
}
|
||||
|
||||
// database file check
|
||||
if (empty($dbFile) || !file_exists($dbFile)) {
|
||||
throw new Exception('Database file is not found.');
|
||||
}
|
||||
|
||||
// connect to database
|
||||
// FIXME: add mysql/mariadb option
|
||||
try {
|
||||
$this->pdo = new PDO("sqlite:" . $dbFile);
|
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException $e) {
|
||||
throw new Exception('DB connection failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getConnection() {
|
||||
return $this->pdo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,115 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Participant {
|
||||
private $db;
|
||||
private $queries;
|
||||
|
||||
public function __construct($database) {
|
||||
$this->db = $database->getConnection();
|
||||
$this->queries = include('queries.php');
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant ID
|
||||
public function conferenceByParticipantId($participant_id, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['conference_by_participant_id'];
|
||||
$sql = sprintf($sql, $participant_id, $from_time, $until_time, $participant_id, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant name (stats_id)
|
||||
public function conferenceByParticipantName($participant_name, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['participant_by_stats_id'];
|
||||
$sql = sprintf($sql, $participant_name, $from_time, $until_time, $participant_name, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// search/list specific participant IP
|
||||
public function conferenceByParticipantIP($participant_ip, $from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['participant_by_ip'];
|
||||
$sql = sprintf($sql, $participant_ip, $from_time, $until_time, $participant_ip, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
// list of all conferences
|
||||
public function participantsAll($from_time, $until_time) {
|
||||
|
||||
// time period drill-down
|
||||
// FIXME make it similar to the bash version
|
||||
if (empty($from_time)) {
|
||||
$from_time = '0000-01-01';
|
||||
}
|
||||
if (empty($until_time)) {
|
||||
$until_time = '9999-12-31';
|
||||
}
|
||||
|
||||
// this is needed for compatibility with the bash version, so we use '%s' placeholders
|
||||
$from_time = htmlspecialchars(strip_tags($from_time));
|
||||
$until_time = htmlspecialchars(strip_tags($until_time));
|
||||
$sql = $this->queries['participants_all'];
|
||||
$sql = sprintf($sql, $from_time, $until_time);
|
||||
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute();
|
||||
|
||||
return $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,314 +0,0 @@
|
|||
<?php
|
||||
|
||||
// all sql queries for the jilo database in one place
|
||||
|
||||
return [
|
||||
|
||||
// list of conferences for time period (if given)
|
||||
// fields: component, duration, conference ID, conference name, number of participants, name count (the conf name is found), conference host
|
||||
'conferences_all_formatted' => "
|
||||
SELECT DISTINCT
|
||||
c.jitsi_component,
|
||||
(SELECT ce.time
|
||||
FROM conference_events ce
|
||||
WHERE
|
||||
ce.conference_id = c.conference_id
|
||||
AND
|
||||
ce.conference_event = 'conference created')
|
||||
AS start,
|
||||
(SELECT ce.time
|
||||
FROM conference_events ce
|
||||
WHERE
|
||||
ce.conference_id = c.conference_id
|
||||
AND
|
||||
ce.conference_event = 'conference expired')
|
||||
AS end,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
(SELECT COUNT(pe.participant_id)
|
||||
FROM participant_events pe
|
||||
WHERE
|
||||
pe.event_type = 'participant joining'
|
||||
AND
|
||||
pe.event_param = c.conference_id) AS participants,
|
||||
name_counts.name_count,
|
||||
c.conference_host
|
||||
FROM
|
||||
conferences c
|
||||
JOIN (
|
||||
SELECT
|
||||
conference_name,
|
||||
COUNT(*) AS name_count
|
||||
FROM
|
||||
conferences
|
||||
GROUP BY
|
||||
conference_name
|
||||
) AS name_counts ON c.conference_name = name_counts.conference_name
|
||||
JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE (ce.time >= '%s 00:00:00' AND ce.time <= '%s 23:59:59')
|
||||
ORDER BY
|
||||
c.id;",
|
||||
|
||||
|
||||
// search for a conference by its ID for a time period (if given)
|
||||
'conference_by_id' => "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
c.conference_id = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
c.conference_id = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time;",
|
||||
|
||||
|
||||
// search for a conference by its name for a time period (if given)
|
||||
'conference_by_name' => "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
c.conference_name = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
c.conference_name = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time;",
|
||||
|
||||
|
||||
// list all participants
|
||||
'participants_all' => "
|
||||
SELECT DISTINCT
|
||||
p.jitsi_component, p.endpoint_id, p.conference_id
|
||||
FROM
|
||||
participants p
|
||||
JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59'
|
||||
ORDER BY p.id;",
|
||||
|
||||
|
||||
// list conferences where participant ID (endpoint_id) is found
|
||||
'conference_by_participant_id' => "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
p.endpoint_id = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
participant_id = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time;",
|
||||
|
||||
|
||||
// list conferences where participant name (stats_id) is found
|
||||
'participant_by_stats_id' => "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.event_type = 'stats_id' AND pe.event_param LIKE '%%%s%%'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
event_type = 'stats_id' AND event_param LIKE '%%%s%%'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time;",
|
||||
|
||||
|
||||
// list conferences where participant IP is found
|
||||
'participant_by_ip' => "
|
||||
SELECT
|
||||
pe.time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
pe.loglevel,
|
||||
pe.event_type,
|
||||
p.endpoint_id AS participant_id,
|
||||
pe.event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
LEFT JOIN
|
||||
participants p ON c.conference_id = p.conference_id
|
||||
LEFT JOIN
|
||||
participant_events pe ON p.endpoint_id = pe.participant_id
|
||||
WHERE
|
||||
pe.event_type = 'pair selected' AND pe.event_param = '%s'
|
||||
AND (pe.time >= '%s 00:00:00' AND pe.time <= '%s 23:59:59')
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
ce.time AS event_time,
|
||||
c.conference_id,
|
||||
c.conference_name,
|
||||
c.conference_host,
|
||||
ce.loglevel,
|
||||
ce.conference_event AS event_type,
|
||||
NULL AS participant_id,
|
||||
ce.conference_param AS event_param
|
||||
FROM
|
||||
conferences c
|
||||
LEFT JOIN
|
||||
conference_events ce ON c.conference_id = ce.conference_id
|
||||
WHERE
|
||||
event_type = 'pair selected' AND event_param = '%s'
|
||||
AND (event_time >= '%s 00:00:00' AND event_time <= '%s 23:59:59')
|
||||
|
||||
ORDER BY
|
||||
pe.time;",
|
||||
|
||||
|
||||
// list of jitsi component events
|
||||
'jitsi_components' => "
|
||||
SELECT jitsi_component, loglevel, time, component_id, event_type, event_param
|
||||
FROM
|
||||
jitsi_components
|
||||
WHERE
|
||||
jitsi_component = %s
|
||||
AND
|
||||
component_id = %s
|
||||
AND
|
||||
(time >= '%s 00:00:00' AND time <= '%s 23:59:59')
|
||||
ORDER BY
|
||||
time;",
|
||||
|
||||
|
||||
];
|
||||
|
||||
?>
|
|
@ -8,9 +8,13 @@
|
|||
* License: GPLv2
|
||||
* Project URL: https://lindeas.com/jilo
|
||||
* Year: 2024
|
||||
* Version: 0.1.1
|
||||
* Version: 0.2
|
||||
*/
|
||||
|
||||
// we start output buffering and.
|
||||
// flush it later only when there is no redirect
|
||||
ob_start();
|
||||
|
||||
// error reporting, comment out in production
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
|
@ -31,26 +35,46 @@ $allowed_urls = [
|
|||
];
|
||||
|
||||
// cnfig file
|
||||
$config_file = '/home/yasen/work/code/git/lindeas-code/jilo-web/jilo-web.conf.php';
|
||||
if (file_exists($config_file)) {
|
||||
require_once $config_file;
|
||||
// possible locations, in order of preference
|
||||
$config_file_locations = [
|
||||
__DIR__ . '/../app/config/jilo-web.conf.php',
|
||||
__DIR__ . '/../jilo-web.conf.php',
|
||||
'/srv/jilo-web/jilo-web.conf.php',
|
||||
'/opt/jilo-web/jilo-web.conf.php'
|
||||
];
|
||||
$config_file = null;
|
||||
// try to find the config file
|
||||
foreach ($config_file_locations as $location) {
|
||||
if (file_exists($location)) {
|
||||
$config_file = $location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if found, use it
|
||||
if ($config_file) {
|
||||
$config = require $config_file;
|
||||
} else {
|
||||
die('Config file not found');
|
||||
}
|
||||
|
||||
$app_root = $config['folder'];
|
||||
|
||||
session_name('jilo');
|
||||
session_start();
|
||||
|
||||
if (isset($_GET['page'])) {
|
||||
$page = $_GET['page'];
|
||||
} elseif (isset($_POST['page'])) {
|
||||
$page = $_POST['page'];
|
||||
if (isset($_REQUEST['page'])) {
|
||||
$page = $_REQUEST['page'];
|
||||
} else {
|
||||
$page = 'front';
|
||||
}
|
||||
if (isset($_REQUEST['item'])) {
|
||||
$item = $_REQUEST['item'];
|
||||
} else {
|
||||
$item = '';
|
||||
}
|
||||
|
||||
// check if logged in
|
||||
unset($user);
|
||||
if (isset($_COOKIE['username'])) {
|
||||
if ( !isset($_SESSION['username']) ) {
|
||||
$_SESSION['username'] = $_COOKIE['username'];
|
||||
|
@ -72,6 +96,9 @@ if (isset($_SESSION['error'])) {
|
|||
$error = $_SESSION['error'];
|
||||
}
|
||||
|
||||
// by default we connect ot the first configured platform
|
||||
$platform_id = $_REQUEST['platform'] ?? '0';
|
||||
|
||||
// page building
|
||||
if (in_array($page, $allowed_urls)) {
|
||||
// logout is a special case, as we can't use session vars for notices
|
||||
|
@ -83,27 +110,37 @@ if (in_array($page, $allowed_urls)) {
|
|||
setcookie('username', "", time() - 100, $config['folder'], $config['domain'], isset($_SERVER['HTTPS']), true);
|
||||
|
||||
$notice = "You were logged out.<br />You can log in again.";
|
||||
include 'templates/header.php';
|
||||
include 'templates/menu.php';
|
||||
include 'templates/message.php';
|
||||
include 'pages/login.php';
|
||||
include '../app/templates/page-header.php';
|
||||
include '../app/templates/page-menu.php';
|
||||
include '../app/templates/block-message.php';
|
||||
include '../app/pages/login.php';
|
||||
|
||||
// all other normal pages
|
||||
} else {
|
||||
include 'templates/header.php';
|
||||
include 'templates/menu.php';
|
||||
include 'templates/message.php';
|
||||
include "pages/{$page}.php";
|
||||
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/{$page}.php";
|
||||
}
|
||||
|
||||
// the page is not in allowed urls, loading front page
|
||||
} else {
|
||||
include 'templates/header.php';
|
||||
include 'templates/menu.php';
|
||||
include 'templates/message.php';
|
||||
include 'pages/front.php';
|
||||
$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';
|
||||
}
|
||||
include 'templates/footer.php';
|
||||
include '../app/templates/page-footer.php';
|
||||
|
||||
// flush the output buffer and show the page
|
||||
ob_end_flush();
|
||||
|
||||
// clear errors and notices before next page just in case
|
||||
unset($_SESSION['error']);
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/component.php';
|
||||
|
||||
// FIXME move thi sto a special function
|
||||
$time_range_specified = false;
|
||||
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($_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;
|
||||
}
|
||||
|
||||
// jitsi component events list
|
||||
// we use $_REQUEST, so that both links and forms work
|
||||
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';
|
||||
}
|
||||
|
||||
// connect to database
|
||||
try {
|
||||
$db = new Database($config['jilo_database']);
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Component events listings
|
||||
//
|
||||
|
||||
|
||||
// list of all component events (default)
|
||||
//if ($jitsi_component) {
|
||||
try {
|
||||
$component = new Component($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $component->jitsiComponents($jitsi_component, $component_id, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$components = array();
|
||||
$components['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$component_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'loglevel' => $loglevel,
|
||||
'time' => $time,
|
||||
'component ID' => $component_id,
|
||||
'event' => $event_type,
|
||||
'param' => $event_param,
|
||||
);
|
||||
// populate the result array
|
||||
array_push($components['records'], $component_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
|
||||
// format the header message
|
||||
echo "<div class=\"results-header\">\n";
|
||||
if (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
echo "<div class=\"results-message\">Jitsi events for component <strong>" . $_REQUEST['name'] . "</strong>";
|
||||
} elseif (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
echo "<div class=\"results-message\">Jitsi events for component ID <br /><strong>" . $_REQUEST['id'] . "</strong>";
|
||||
} else {
|
||||
echo "<div class=\"results-message\">Jitsi events for <strong>all components</strong>";
|
||||
}
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($components['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($components['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($components['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'component ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=components&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'component') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=components&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching Jitsi component events found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
//}
|
||||
|
||||
?>
|
|
@ -1,359 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/conference.php';
|
||||
|
||||
// FIXME move thi sto a special function
|
||||
$time_range_specified = false;
|
||||
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($_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;
|
||||
}
|
||||
|
||||
// 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 (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$conference_id = $_REQUEST['id'];
|
||||
unset($_REQUEST['name']);
|
||||
unset($conference_name);
|
||||
} elseif (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
unset($conference_id);
|
||||
$conference_name = $_REQUEST['name'];
|
||||
} else {
|
||||
unset($conference_id);
|
||||
unset($conference_name);
|
||||
}
|
||||
|
||||
// connect to database
|
||||
try {
|
||||
$db = new Database($config['jilo_database']);
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Conference listings
|
||||
//
|
||||
|
||||
|
||||
// search and list specific conference ID
|
||||
if (isset($conference_id)) {
|
||||
|
||||
try {
|
||||
$conference = new Conference($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferenceById($conference_id, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">Conferences with ID matching \"<strong>$conference_id</strong>\"";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
$stats_id = false;
|
||||
$participant_ip = false;
|
||||
if ($row['event'] === 'stats_id') $stats_id = true;
|
||||
if ($row['event'] === 'pair selected') $participant_ip = true;
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference ID' && $column === $conference_id) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($stats_id && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($participant_ip && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&ip=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
|
||||
// search and list specific conference ID
|
||||
} elseif (isset($conference_name)) {
|
||||
|
||||
try {
|
||||
$conference = new Conference($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferenceByName($conference_name, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">Conferences with name matching \"<strong>$conference_name</strong>\"";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
$stats_id = false;
|
||||
$participant_ip = false;
|
||||
if ($row['event'] === 'stats_id') $stats_id = true;
|
||||
if ($row['event'] === 'pair selected') $participant_ip = true;
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference name' && $column === $conference_name) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'participant ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($stats_id && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($participant_ip && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&ip=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
|
||||
// list of all conferences (default)
|
||||
} else {
|
||||
try {
|
||||
$conference = new Conference($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">All conferences";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,13 +0,0 @@
|
|||
<?php ?>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Jilo web configuration</p>
|
||||
|
||||
<ul>
|
||||
<?php foreach ($config as $config_item=>$config_value) { ?>
|
||||
<li><?php echo htmlspecialchars($config_item) . ': ' . htmlspecialchars($config_value ?? ''); ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
||||
</div>
|
|
@ -1,241 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/conference.php';
|
||||
|
||||
// connect to database
|
||||
try {
|
||||
$db = new Database($config['jilo_database']);
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
//
|
||||
// dashboard widget listings
|
||||
//
|
||||
|
||||
// conferences in last 7 days
|
||||
try {
|
||||
$conference = new Conference($db);
|
||||
|
||||
// conferences for last 2 days
|
||||
$from_time = date('Y-m-d', time() - 60 * 60 * 24 * 2);
|
||||
$until_time = date('Y-m-d', time());
|
||||
$time_range_specified = true;
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<a style=\"text-decoration: none;\" data-toggle=\"collapse\" href=\"#collapseLastDays\" role=\"button\" aria-expanded=\"true\" aria-controls=\"collapseLastDays\">";
|
||||
echo "<div class=\"card bg-light card-body\">Conferences for the last 2 days</div></a>";
|
||||
|
||||
echo "<div class=\"collapse show\" id=\"collapseLastDays\">";
|
||||
|
||||
if ($time_range_specified) {
|
||||
echo "<p class=\"m-3\">time period: <strong>$from_time - $until_time</strong></p>";
|
||||
}
|
||||
|
||||
//// filters - time selection and sorting dropdowns
|
||||
//include 'templates/results-filter.php';
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"thead-dark\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference ID' && $column === $conference_id) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
echo "</div>";
|
||||
|
||||
echo "<br />";
|
||||
|
||||
// last 10 conferences
|
||||
try {
|
||||
$conference = new Conference($db);
|
||||
|
||||
// all time
|
||||
$from_time = '0000-01-01';
|
||||
$until_time = '9999-12-31';
|
||||
$time_range_specified = false;
|
||||
// number of conferences to show
|
||||
$conference_number = 10;
|
||||
|
||||
// prepare the result
|
||||
$search = $conference->conferencesAllFormatted($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
$i = 0;
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
|
||||
// we don't have duration field, so we calculate it
|
||||
if (!empty($start) && !empty($end)) {
|
||||
$duration = gmdate("H:i:s", abs(strtotime($end) - strtotime($start)));
|
||||
} else {
|
||||
$duration = '';
|
||||
}
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'participants' => $participants,
|
||||
'name count' => $name_count,
|
||||
'conference host' => $conference_host
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
|
||||
// we only take the first 10 results
|
||||
$i++;
|
||||
if ($i == 10) break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<a style=\"text-decoration: none;\" data-toggle=\"collapse\" href=\"#collapseLastConferences\" role=\"button\" aria-expanded=\"true\" aria-controls=\"collapseLastConferences\">";
|
||||
echo "<div class=\"card bg-light card-body\">The last $conference_number conferences</div></a>";
|
||||
|
||||
echo "<div class=\"collapse show\" id=\"collapseLastConferences\">";
|
||||
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
|
||||
//// filters - time selection and sorting dropdowns
|
||||
//include 'templates/results-filter.php';
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
echo "</div>";
|
||||
|
||||
|
||||
?>
|
|
@ -1,444 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/participant.php';
|
||||
|
||||
// FIXME move thi sto a special function
|
||||
$time_range_specified = false;
|
||||
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($_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;
|
||||
}
|
||||
|
||||
// participant id/name/IP are specified when searching specific participant(s)
|
||||
// participant name - this is 'stats_id' in the db
|
||||
// either id, name, OR IP - in that order
|
||||
// we use $_REQUEST, so that both links and forms work
|
||||
if (isset($_REQUEST['id']) && $_REQUEST['id'] != '') {
|
||||
$participant_id = $_REQUEST['id'];
|
||||
unset($_REQUEST['name']);
|
||||
unset($participant_name);
|
||||
} elseif (isset($_REQUEST['name']) && $_REQUEST['name'] != '') {
|
||||
unset($participant_id);
|
||||
$participant_name = $_REQUEST['name'];
|
||||
} elseif (isset($_REQUEST['ip']) && $_REQUEST['ip'] != '') {
|
||||
unset($participant_id);
|
||||
$participant_ip = $_REQUEST['ip'];
|
||||
} else {
|
||||
unset($participant_id);
|
||||
unset($participant_name);
|
||||
}
|
||||
|
||||
// connect to database
|
||||
try {
|
||||
$db = new Database($config['jilo_database']);
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Participant listings
|
||||
//
|
||||
|
||||
|
||||
// search and list specific participant ID
|
||||
if (isset($participant_id)) {
|
||||
|
||||
try {
|
||||
$participant = new Participant($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $participant->conferenceByParticipantId($participant_id, $from_time, $until_time, $participant_id, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">Conferences with participant ID matching \"<strong>$participant_id</strong>\"";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
$stats_id = false;
|
||||
$participant_ip = false;
|
||||
if ($row['event'] === 'stats_id') $stats_id = true;
|
||||
if ($row['event'] === 'pair selected') $participant_ip = true;
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'participant ID' && $column === $participant_id) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($stats_id && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($participant_ip && $key === 'parameter') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&ip=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
|
||||
// search and list specific participant name (stats_id)
|
||||
} elseif (isset($participant_name)) {
|
||||
|
||||
try {
|
||||
$participant = new Participant($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $participant->conferenceByParticipantName($participant_name, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">Conferences with participant name (stats_id) matching \"<strong>$participant_name</strong>\"";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope-\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'parameter' && $column === $participant_name) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'participant ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
|
||||
// search and list specific participant IP
|
||||
} elseif (isset($participant_ip)) {
|
||||
|
||||
try {
|
||||
$participant = new Participant($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $participant->conferenceByParticipantIP($participant_ip, $from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$conferences = array();
|
||||
$conferences['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$conference_record = array(
|
||||
// assign title to the field in the array record
|
||||
'time' => $time,
|
||||
'conference ID' => $conference_id,
|
||||
'conference name' => $conference_name,
|
||||
'conference host' => $conference_host,
|
||||
'loglevel' => $loglevel,
|
||||
'participant ID' => $participant_id,
|
||||
'event' => $event_type,
|
||||
'parameter' => $event_param
|
||||
);
|
||||
// populate the result array
|
||||
array_push($conferences['records'], $conference_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">Conferences with participant IP matching \"<strong>$participant_ip</strong>\"";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($conferences['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($conferences['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th scope=\"col\">" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($conferences['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'parameter' && $column === $participant_ip) {
|
||||
echo "\t\t\t\t<td><strong>" . htmlspecialchars($column ?? '') . "</strong></td>\n";
|
||||
} elseif ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference name') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&name=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'participant ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching conferences found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
|
||||
// list of all participants (default)
|
||||
} else {
|
||||
try {
|
||||
$participant = new Participant($db);
|
||||
|
||||
// prepare the result
|
||||
$search = $participant->participantsAll($from_time, $until_time);
|
||||
|
||||
if (!empty($search)) {
|
||||
$participants = array();
|
||||
$participants['records'] = array();
|
||||
|
||||
foreach ($search as $item) {
|
||||
extract($item);
|
||||
$participant_record = array(
|
||||
// assign title to the field in the array record
|
||||
'component' => $jitsi_component,
|
||||
'participant ID' => $endpoint_id,
|
||||
'conference ID' => $conference_id,
|
||||
);
|
||||
// populate the result array
|
||||
array_push($participants['records'], $participant_record);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = 'Error: ' . $e->getMessage();
|
||||
include 'templates/message.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
// display the result
|
||||
echo "<div class=\"results-header\">\n";
|
||||
echo "<div class=\"results-message\">All participants";
|
||||
if ($time_range_specified) {
|
||||
echo "<br />for the time period <strong>$from_time - $until_time</strong>";
|
||||
}
|
||||
echo "</div>\n\n";
|
||||
|
||||
// filters - time selection and sorting dropdowns
|
||||
include 'templates/results-filter.php';
|
||||
|
||||
echo "</div>\n\n";
|
||||
|
||||
// results table
|
||||
echo "<div class=\"mb-5\">\n";
|
||||
|
||||
if (!empty($participants['records'])) {
|
||||
|
||||
echo "\t<table class=\"table table-striped table-hover table-bordered\">\n";
|
||||
|
||||
echo "\t\t<thead class=\"table-secondary\">\n";
|
||||
echo "\t\t\t<tr>\n";
|
||||
|
||||
// table headers
|
||||
foreach (array_keys($participants['records'][0]) as $header) {
|
||||
echo "\t\t\t\t<th>" . htmlspecialchars($header) . "</th>\n";
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
echo "\t\t</thead>\n";
|
||||
|
||||
echo "\t\t<tbody>\n";
|
||||
|
||||
//table rows
|
||||
foreach ($participants['records'] as $row) {
|
||||
echo "\t\t\t<tr>\n";
|
||||
// sometimes $column is empty, we make it '' then
|
||||
foreach ($row as $key => $column) {
|
||||
if ($key === 'participant ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=participants&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} elseif ($key === 'conference ID') {
|
||||
echo "\t\t\t\t<td><a href=\"$app_root?page=conferences&id=" . htmlspecialchars($column ?? '') . "\">" . htmlspecialchars($column ?? '') . "</a></td>\n";
|
||||
} else {
|
||||
echo "\t\t\t\t<td>" . htmlspecialchars($column ?? '') . "</td>\n";
|
||||
}
|
||||
}
|
||||
echo "\t\t\t</tr>\n";
|
||||
}
|
||||
|
||||
echo "\t\t</tbody>\n";
|
||||
echo "\t</table>\n";
|
||||
|
||||
} else {
|
||||
echo '<p class="m-3">No matching participants found.</p>';
|
||||
}
|
||||
echo "\n</div>\n";
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,11 +0,0 @@
|
|||
<?php ?>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Profile of <?= $user ?></p>
|
||||
|
||||
<ul>
|
||||
<li>username: <?= $_SESSION['username'] ?></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'classes/database.php';
|
||||
require 'classes/user.php';
|
||||
unset($error);
|
||||
|
||||
try {
|
||||
$db = new Database($config['database']);
|
||||
$user = new User($db);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
|
||||
// redirect to login
|
||||
if ( $user->register($username, $password) ) {
|
||||
$_SESSION['notice'] = "Registration successful.<br />You can log in now.";
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
// registration fail, redirect to login
|
||||
} else {
|
||||
$_SESSION['error'] = "Registration failed.";
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
include 'templates/message.php';
|
||||
include 'templates/form-register.php';
|
||||
|
||||
?>
|
|
@ -78,31 +78,6 @@
|
|||
color: white;
|
||||
}
|
||||
|
||||
/*
|
||||
.results {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.results table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.results table, th, td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.results th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
.results th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.results p {
|
||||
text-align: center;
|
||||
}
|
||||
*/
|
||||
|
||||
.results-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -120,3 +95,65 @@
|
|||
.widget {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
|
||||
/* collapsing sidebar */
|
||||
.toggle-sidebar-button {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -10px;
|
||||
z-index: 100;
|
||||
margin: 10px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
padding-left: 2px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
.sidebar-wrapper {
|
||||
position: relative;
|
||||
width: 275px;
|
||||
transition: width 0.5s ease;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.sidebar-wrapper.collapsed {
|
||||
width: 3em;
|
||||
}
|
||||
.sidebar-collapsed .sidebar-wrapper {
|
||||
width: 3em;
|
||||
}
|
||||
.sidebar-content {
|
||||
width: 250px;
|
||||
border: none;
|
||||
}
|
||||
.list-group-item i {
|
||||
margin-right: 10px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
transition: width 0.5s ease;
|
||||
width: 80%;
|
||||
}
|
||||
.main-content.expanded {
|
||||
width: calc(70% + 250px);
|
||||
}
|
||||
.sidebar-collapsed .main-content {
|
||||
width: calc(70% + 3em);
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 35px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.logo-link {
|
||||
border: 1px solid white;
|
||||
margin-top: 2px;
|
||||
margin-left: 2px;
|
||||
background-color: lightseagreen;
|
||||
}
|
||||
|
||||
.sidebar-content a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
|
@ -0,0 +1,49 @@
|
|||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
var mainContent = document.getElementById('mainContent');
|
||||
var toggleButton = document.getElementById('toggleSidebarButton');
|
||||
|
||||
// update localStorage based on the current state
|
||||
function updateStorage() {
|
||||
var isSidebarCollapsed = sidebar.classList.contains('collapsed');
|
||||
localStorage.setItem('sidebarState', isSidebarCollapsed ? 'collapsed' : 'expanded');
|
||||
}
|
||||
|
||||
// apply saved state
|
||||
function applySavedState() {
|
||||
var savedState = localStorage.getItem('sidebarState');
|
||||
if (savedState === 'collapsed') {
|
||||
toggleButton.value = ">>";
|
||||
toggleButton.textContent = ">>";
|
||||
sidebar.classList.add('collapsed');
|
||||
mainContent.classList.add('expanded');
|
||||
} else {
|
||||
toggleButton.value = "<<";
|
||||
toggleButton.textContent = "<<";
|
||||
sidebar.classList.remove('collapsed');
|
||||
mainContent.classList.remove('expanded');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
applySavedState();
|
||||
|
||||
toggleButton.addEventListener('click', function () {
|
||||
// toggle sidebar and main content
|
||||
sidebar.classList.toggle('collapsed');
|
||||
document.documentElement.classList.toggle('sidebar-collapsed');
|
||||
mainContent.classList.toggle('expanded');
|
||||
// Toggle the value between ">>" and "<<"
|
||||
if (toggleButton.value === ">>") {
|
||||
toggleButton.value = "<<";
|
||||
toggleButton.textContent = "<<";
|
||||
} else {
|
||||
toggleButton.value = ">>";
|
||||
toggleButton.textContent = ">>";
|
||||
}
|
||||
|
||||
// Update with the new state
|
||||
updateStorage();
|
||||
});
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
<div id="footer">Jilo Web <?= $config['version'] ?> ©2024 - web interface for <a href="https://lindeas.com/jilo">Jilo</a></div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
<h2>Login</h2>
|
||||
|
||||
<div class="login-form">
|
||||
<form method="POST" action="?page=login">
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<br />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<br />
|
||||
<label for="remember_me">
|
||||
<input type="checkbox" id="remember_me" name="remember_me" />
|
||||
remember me
|
||||
</label>
|
||||
<br />
|
||||
<input type="submit" value="Login" />
|
||||
</form>
|
||||
</div>
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
<h2>Register</h2>
|
||||
|
||||
<div class="register-form">
|
||||
<form method="POST" action="?page=register">
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<br />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<br />
|
||||
<input type="submit" value="Register" />
|
||||
</form>
|
||||
</div>
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
<div class="menu-container">
|
||||
<ul class="menu-left">
|
||||
<li><a href="index.php">home</a></li>
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
<li><a href="?page=config">config</a></li>
|
||||
<li><a href="?page=conferences">conferences</a></li>
|
||||
<li><a href="?page=participants">participants</a></li>
|
||||
<li><a href="?page=components">components</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
||||
<ul class="menu-right">
|
||||
<?php if ( isset($_SESSION['username']) ) { ?>
|
||||
<li><a href="?page=profile"><?= $user ?></a></li>
|
||||
<li><a href="?page=logout">logout</a></li>
|
||||
<?php } else { ?>
|
||||
<li><a href="?page=login">login</a></li>
|
||||
<li><a href="?page=register">register</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
<?php if (isset($error)) { ?>
|
||||
<div class="error">
|
||||
<?php echo $error; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (isset($notice)) { ?>
|
||||
<div class="notice">
|
||||
<?php echo $notice; ?>
|
||||
</div>
|
||||
<?php } ?>
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
<div class="results-filter">
|
||||
|
||||
<form method="POST" id="filter_form" action="?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=\"" . $_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=\"" . $_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=\"" . $_REQUEST['ip'] . "\"" ?> maxlength="15" size="15" />
|
||||
<?php } ?>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="float-end pt-3">
|
||||
|
||||
<input type="button" onclick="clearFilter()" value="clear" />
|
||||
|
||||
<input type="submit" value="search" />
|
||||
|
||||
</div>
|
||||
|
||||
</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>
|
Loading…
Reference in New Issue