This commit is contained in:
Xes
2025-08-14 22:39:38 +02:00
parent 3641e93527
commit 5403f346e3
3370 changed files with 327179 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
<?php
/* For license terms, see /license.txt */
class Justification extends Plugin
{
protected function __construct()
{
parent::__construct(
'1.2',
'Julio Montoya, Nicolas Ducoulombier',
[
'tool_enable' => 'boolean',
'notification_to_creator_only' => 'boolean',
'access_for_session_admin' => 'boolean',
'default_course_id' => 'text',
]
);
}
/**
* @return $this
*/
public static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
public function getJustification($id)
{
$id = (int) $id;
$sql = 'SELECT * FROM justification_document WHERE id = '.$id;
$query = Database::query($sql);
return Database::fetch_array($query, 'ASSOC');
}
public function getUserJustificationList($userId)
{
$userId = (int) $userId;
$sql = "SELECT * FROM justification_document_rel_users WHERE user_id = $userId ";
$query = Database::query($sql);
return Database::store_result($query, 'ASSOC');
}
public function getUserJustification($id)
{
$id = (int) $id;
$sql = "SELECT * FROM justification_document_rel_users WHERE id = $id ";
$query = Database::query($sql);
return Database::fetch_array($query, 'ASSOC');
}
public function getList()
{
$sql = 'SELECT * FROM justification_document ORDER BY name ';
$query = Database::query($sql);
return Database::store_result($query, 'ASSOC');
}
/**
* Install.
*/
public function install()
{
$sql = "CREATE TABLE IF NOT EXISTS justification_document (
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
code TEXT NULL,
name TEXT NULL,
validity_duration INT,
comment TEXT NULL,
date_manual_on INT
)";
Database::query($sql);
$sql = "CREATE TABLE IF NOT EXISTS justification_document_rel_users (
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
justification_document_id INT NOT NULL,
file_path VARCHAR(255),
user_id INT,
date_validity DATE
)";
Database::query($sql);
}
public function uninstall()
{
$sql = 'DROP TABLE IF EXISTS justification_document';
Database::query($sql);
$sql = 'DROP TABLE IF EXISTS justification_document_rel_users';
Database::query($sql);
}
}

View File

@@ -0,0 +1,39 @@
Justification
==============
1. Enable the plugin.
2. Create the justification files in plugin/justification/list.php
When activating the justification plugin it adds a link at the bottom of the plateform block of the administration page to open plugin/justification/list.php to create and manage the justification needed.
On this page the admin can manage the list of justification that would be asked to users, and select a course for automatic inscription if the justificatives are completed and desinscription if justicatives are not completed or outdated. For the automatic subscription and removal you need to create a cron to run plugin/justification/cron.php periodically to do the verification.
The justification plugin only activate a new tab in the profile for the user to upload some justification (the list of which are defined by the administrator on the page plugin/justification/list.php indicated above).
If the notification system is activated then you have the ability to create notification to be sent before the expiration of the justification if configured so.
To activate it you have to set it in app/config/configuration.php with :
```
// Show notification events
/*CREATE TABLE IF NOT EXISTS notification_event (
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
title VARCHAR(255),
content TEXT,
link TEXT,
persistent INT,
day_diff INT,
event_type VARCHAR(255)
);
ALTER TABLE notification_event ADD COLUMN event_id INT NULL;
CREATE TABLE IF NOT EXISTS notification_event_rel_user (
id INT UNSIGNED AUTO_INCREMENT NOT NULL,
event_id INT unsigned,
user_id INT,
INDEX FK_EVENT (event_id),
INDEX FK_USER (user_id),
PRIMARY KEY (id)
);
ALTER TABLE notification_event_rel_user ADD CONSTRAINT FK_EVENT FOREIGN KEY (event_id) REFERENCES notification_event (id) ON DELETE CASCADE;
ALTER TABLE notification_event_rel_user ADD CONSTRAINT FK_USER FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE;
*/
// create new user text extra field called 'notification_event' to save the persistent settings.
// $_configuration['notification_event'] = false;
```

View File

@@ -0,0 +1,68 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$tool = 'justification';
$plugin = Justification::create();
$tpl = new Template($tool);
$fields = [];
$form = new FormValidator('add');
$form->addText('name', get_lang('Name'));
$form->addText('code', $plugin->get_lang('JustificationCode'));
$form->addNumeric('validity_duration', $plugin->get_lang('ValidityDuration'));
$form->addCheckBox('date_manual_on', $plugin->get_lang('DateManualOn'));
$form->addTextarea('comment', get_lang('Comment'));
$form->addButtonSave(get_lang('Save'));
if ($form->validate()) {
$values = $form->getSubmitValues();
$dateManual = isset($values['date_manual_on']) ? 1 : 0;
$cleanedCode = api_replace_dangerous_char($values['code']);
$code = Database::escape_string($cleanedCode);
$sql = "SELECT * FROM justification_document WHERE code = '$code' ";
$result = Database::query($sql);
$data = Database::fetch_array($result);
$message = Display::return_message(get_lang('ThisCodeAlradyExists'), 'warning');
if (empty($data)) {
$params = [
'name' => $values['name'],
'code' => $cleanedCode,
'validity_duration' => $values['validity_duration'],
'date_manual_on' => $dateManual,
'comment' => $values['comment'],
];
Database::insert('justification_document', $params);
$message = Display::return_message(get_lang('Saved'));
}
Display::addFlash($message);
$url = api_get_path(WEB_PLUGIN_PATH).'justification/list.php?';
header('Location: '.$url);
exit;
}
$actionLinks = Display::toolbarButton(
$plugin->get_lang('Back'),
api_get_path(WEB_PLUGIN_PATH).'justification/list.php',
'arrow-left',
'primary'
);
$tpl->assign(
'actions',
Display::toolbarAction('toolbar', [$actionLinks])
);
$content = $form->returnForm();
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,88 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
$plugin = Justification::create();
$courseId = api_get_setting('justification_default_course_id', 'justification');
echo 'Justification CRON - '.api_get_local_time().PHP_EOL;
if (empty($courseId)) {
echo 'No course was set';
exit;
}
$courseInfo = api_get_course_info_by_id($courseId);
if (empty($courseInfo)) {
echo "Course #$courseId doesn't exist";
exit;
}
$fieldList = $plugin->getList();
$totalFields = count($fieldList);
if (empty($fieldList)) {
echo 'No fields to check. Please add them in the justification plugin';
exit;
}
$userList = UserManager::get_user_list();
$count = count($userList);
echo "#$count users found".PHP_EOL;
$currentDate = api_get_utc_datetime();
foreach ($userList as $user) {
$userId = $user['id'];
echo "Checking user id #$userId".PHP_EOL;
$userJustificationList = $plugin->getUserJustificationList($userId);
$userJustificationDocumentList = array_column($userJustificationList, 'date_validity', 'justification_document_id');
if (count($userJustificationList) < $totalFields) {
unsubscribeUser($userId, $courseInfo);
continue;
}
if (count($userJustificationList) >= $totalFields) {
$successList = [];
foreach ($fieldList as $field) {
if (isset($userJustificationDocumentList[$field['id']])) {
$dateValidity = $userJustificationDocumentList[$field['id']];
if ($dateValidity > $currentDate) {
$successList[] = true;
}
}
}
$countSuccess = count($successList);
if ($countSuccess === $totalFields) {
subscribeUser($userId, $courseInfo);
continue;
} else {
echo "User #$userId only got $countSuccess justification(s) out of $totalFields.".PHP_EOL;
}
}
unsubscribeUser($userId, $courseInfo);
}
function unsubscribeUser($userId, $courseInfo)
{
$courseId = $courseInfo['real_id'];
CourseManager::unsubscribe_user($userId, $courseInfo['code']);
echo "Unsubscribe user id #$userId to course #$courseId".PHP_EOL;
}
function subscribeUser($userId, $courseInfo)
{
$courseId = $courseInfo['real_id'];
$isUserSubscribed = CourseManager::is_user_subscribed_in_course($userId, $courseInfo['code']);
if ($isUserSubscribed === false) {
CourseManager::subscribeUser($userId, $courseInfo['code'], STUDENT);
echo "Subscribe user id #$userId to course #$courseId".PHP_EOL;
} else {
echo "Nothing to do user id #$userId is already subscribed to #$courseId".PHP_EOL;
}
}

View File

@@ -0,0 +1,76 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$tool = 'justification';
$plugin = Justification::create();
$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
if (empty($id)) {
api_not_allowed();
}
$justification = $plugin->getJustification($id);
$tpl = new Template($tool);
$fields = [];
$form = new FormValidator('add', 'post', api_get_self().'?id='.$id);
$form->addText('name', get_lang('Name'));
$form->addText('code', $plugin->get_lang('JustificationCode'));
$form->addNumeric('validity_duration', $plugin->get_lang('ValidityDuration'));
$form->addCheckBox('date_manual_on', $plugin->get_lang('DateManualOn'));
$form->addTextarea('comment', get_lang('Comment'));
$form->addButtonSave(get_lang('Update'));
$form->setDefaults($justification);
if ($form->validate()) {
$values = $form->getSubmitValues();
$cleanedCode = api_replace_dangerous_char($values['code']);
$code = Database::escape_string($cleanedCode);
$sql = "SELECT * FROM justification_document WHERE code = '$code' AND id <> $id";
$result = Database::query($sql);
$data = Database::fetch_array($result);
$message = Display::return_message(get_lang('ThisCodeAlradyExists'), 'warning');
if (empty($data)) {
$params = [
'name' => $values['name'],
'code' => $cleanedCode,
'validity_duration' => $values['validity_duration'],
'date_manual_on' => (int) $values['date_manual_on'],
'comment' => $values['comment'],
];
Database::update('justification_document', $params, ['id = ?' => $id]);
$message = Display::return_message(get_lang('Saved'));
}
Display::addFlash($message);
$url = api_get_path(WEB_PLUGIN_PATH).'justification/list.php?';
header('Location: '.$url);
exit;
}
$actionLinks = Display::toolbarButton(
$plugin->get_lang('Back'),
api_get_path(WEB_PLUGIN_PATH).'justification/list.php',
'arrow-left',
'primary'
);
$tpl->assign(
'actions',
Display::toolbarAction('toolbar', [$actionLinks])
);
$content = $form->returnForm();
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,4 @@
<?php
/* For license terms, see /license.txt */
$plugin = Justification::create();

View File

@@ -0,0 +1,8 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
Justification::create()->install();

View File

@@ -0,0 +1,114 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
$allowSessionAdmins = api_get_plugin_setting('justification', 'access_for_session_admin') === 'true';
api_protect_admin_script($allowSessionAdmins);
$tool = 'justification';
$plugin = Justification::create();
$tpl = new Template($tool);
$fields = [];
$form = new FormValidator('search', 'get');
$form->addHeader('Search');
$form->addSelectAjax(
'user_id',
get_lang('User'),
[],
[
'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like',
]
);
$form->addButtonSearch(get_lang('Search'));
$tpl->assign('form', $form->returnForm());
$userId = isset($_REQUEST['user_id']) ? (int) $_REQUEST['user_id'] : 0;
if ($form->validate()) {
$userId = $form->getSubmitValue('user_id');
}
if ($userId) {
$tpl->assign('user_info', api_get_user_info($userId));
$list = $plugin->getUserJustificationList($userId);
if ($list) {
foreach ($list as &$item) {
if ($item['date_validity'] < api_get_local_time()) {
$item['date_validity'] = Display::label($item['date_validity'], 'warning');
}
$item['justification'] = $plugin->getJustification($item['justification_document_id']);
$item['file_path'] = Display::url(
$item['file_path'],
api_get_uploaded_web_url('justification', $item['id'], $item['file_path']),
['target' => '_blank']
);
}
}
if (empty($list)) {
Display::addFlash(Display::return_message($plugin->get_lang('NoJustificationFound')));
}
$tpl->assign('list', $list);
}
$tpl->assign('user_id', $userId);
$content = $tpl->fetch('justification/view/justification_user_list.tpl');
$actionLinks = '';
$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : '';
$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
switch ($action) {
case 'edit':
$userJustification = $plugin->getUserJustification($id);
$userInfo = api_get_user_info($userJustification['user_id']);
$form = new FormValidator('edit', 'post', api_get_self().'?a=edit&id='.$id.'&user_id='.$userId);
$form->addHeader($userInfo['complete_name']);
$element = $form->addDatePicker('date_validity', $plugin->get_lang('ValidityDate'));
$element->setValue($userJustification['date_validity']);
$form->addButtonUpdate(get_lang('Update'));
$form->setDefaults($userJustification);
$content = $form->returnForm();
if ($form->validate()) {
$values = $form->getSubmitValues();
$date = Database::escape_string($values['date_validity']);
$sql = "UPDATE justification_document_rel_users SET date_validity = '$date' WHERE id = $id";
Database::query($sql);
Display::addFlash(Display::return_message(get_lang('Updated')));
header('Location: '.api_get_self().'?user_id='.$userId);
exit;
}
break;
case 'delete':
$userJustification = $plugin->getUserJustification($id);
if ($userJustification) {
api_remove_uploaded_file_by_id('justification', $id, $userJustification['file_path']);
$sql = "DELETE FROM justification_document_rel_users WHERE id = $id";
Database::query($sql);
Display::addFlash(Display::return_message(get_lang('Deleted')));
}
header('Location: '.api_get_self().'?user_id='.$userId);
exit;
break;
}
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Back'),
api_get_path(WEB_PLUGIN_PATH).'justification/list.php',
'arrow-left',
'primary'
);
$tpl->assign(
'actions',
Display::toolbarAction('toolbar', [$actionLinks])
);
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,27 @@
<?php
$strings['plugin_title'] = "Justification Plugin";
$strings['plugin_comment'] = "Requires documents from students as administrative justification.";
$strings['tool_enable'] = "Enable";
$strings['ValidityDuration'] = "Validity Duration";
$strings['DateManualOn'] = "Date Manual On";
$strings['JustificationCode'] = "Justification code";
$strings['NoJustificationFound'] = "No justification found";
$strings['ValidityDate'] = "Validity date";
$strings['Justification'] = "Justification";
$strings['MyJustifications'] = "My justifications";
$strings['JustificationSaved'] = "Justification saved";
$strings['default_course_id'] = "Course id";
$strings['SetNewCourse'] = "Set new course";
$strings['SubscribeToASession'] = "Subscribe to a session";
$strings['JustificationName'] = "Justification name";
$strings['JustificationDate'] = "Justification date";
$strings['DocumentListForUserX'] = "Document list of user %s";
$strings['JustificationsCompleted'] = "Justifications completed";
$strings['SendNotificationToAllAdmins'] = "Send a notification to the administrator";
$strings['notification_to_creator_only'] = "Send notification to user's creator only";
$strings['notification_to_creator_only_help'] = "If activated then the notification will be sent only to the user who created the user who send the justifications and not to all admins";
$strings['access_for_session_admin'] = "Enable session admins to manage users in plugin";
$strings['access_for_session_admin_help'] = "If activated it enables session admins to access the plugin and the user's list and justification management.";

View File

@@ -0,0 +1,27 @@
<?php
$strings['plugin_title'] = "Justification Plugin";
$strings['plugin_comment'] = "Demande des documents à valeur de justification administrative.";
$strings['tool_enable'] = "Activer le plugin";
$strings['ValidityDuration'] = "Durée de validité en jour";
$strings['DateManualOn'] = "Autoriser la modification de la date";
$strings['JustificationCode'] = "Code du justificatif";
$strings['NoJustificationFound'] = "Aucun justificatif trouvé";
$strings['ValidityDate'] = "Date de validitée";
$strings['Justification'] = "Justificatif";
$strings['MyJustifications'] = "Mes justificatifs";
$strings['JustificationSaved'] = "Justificatif enregistré";
$strings['default_course_id'] = "id du cours par défaut";
$strings['SetNewCourse'] = "Sélectionner un cours";
$strings['JustificationName'] = "Nom du justificatif";
$strings['JustificationDate'] = "Date du justificatif";
$strings['SubscribeToASession'] = "S'inscrire à une session d'examen";
$strings['DocumentListForUserX'] = "Liste des documents pour %s";
$strings['JustificationsCompleted'] = "Dossier complété";
$strings['SendNotificationToAllAdmins'] = "Envoyer une notification à l'administrateur";
$strings['notification_to_creator_only'] = "Envoyer la notification uniquement au créateur";
$strings['notification_to_creator_only_help'] = "Si cette option est activée alors la notification est envoyée uniquement à l'utilisateur qui a créé l'utilisateur qui envoie les justificatifs et non à tous les admins de la plateforme";
$strings['access_for_session_admin'] = "Permettre aux administrateurs de session de gérer les utilisateurs dans le plugin";
$strings['access_for_session_admin_help'] = "Si activé alors les administrateurs de session peuvent accéder au plugin et à la liste des utilisateurs et la gestion de leurs justificatifs.";

View File

@@ -0,0 +1,27 @@
<?php
$strings['plugin_title'] = "Justification Plugin";
$strings['plugin_comment'] = "Exige la subida de documentos de parte de los alumnos para validación de temas administrativos.";
$strings['tool_enable'] = "Activar el plugin";
$strings['ValidityDuration'] = "Periodo de validez en días";
$strings['DateManualOn'] = "Permitir modificación de fecha";
$strings['JustificationCode'] = "Código del justificativo";
$strings['NoJustificationFound'] = "Ningun justificativo encontrado";
$strings['ValidityDate'] = "Fecha de validez";
$strings['Justification'] = "Justificativo";
$strings['MyJustifications'] = "Mis justificativos";
$strings['JustificationSaved'] = "Justificativo guardado";
$strings['default_course_id'] = "id del courso por defecto";
$strings['SetNewCourse'] = "Eligir un curso";
$strings['JustificationName'] = "Nombre del justificativo";
$strings['JustificationDate'] = "Fecha del justificativo";
$strings['SubscribeToASession'] = "Inscribirse a una sesion de examen";
$strings['DocumentListForUserX'] = "Lista de documentos para %s";
$strings['JustificationsCompleted'] = "justificativos completados";
$strings['SendNotificationToAllAdmins'] = "Enviar una notificación al administrador";
$strings['notification_to_creator_only'] = "Enviar la notificación solo al creador del usuario";
$strings['notification_to_creator_only_help'] = "Si esta opción esta activada entonces la notificación sera enviada solo al usuario que ha creado el usuario quien envia sus justificativo";
$strings['access_for_session_admin'] = "Permitir a los administradores de sesión gestionar los usuarios en el plugin";
$strings['access_for_session_admin_help'] = "Si activado entonces los administradores de sesión pueden acceder al plugin y a la lista de usuarios y gestionar sus justificativos.";

View File

@@ -0,0 +1,66 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
$allowSessionAdmins = api_get_plugin_setting('justification', 'access_for_session_admin') === 'true';
api_protect_admin_script($allowSessionAdmins);
$tool = 'justification';
$plugin = Justification::create();
$tpl = new Template($tool);
$fields = [];
$list = $plugin->getList();
$tpl->assign('list', $list);
$content = $tpl->fetch('justification/view/list.tpl');
$actionLinks = '';
$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : '';
$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
switch ($action) {
case 'delete':
$sql = "DELETE FROM justification_document WHERE id = $id";
Database::query($sql);
Display::addFlash(Display::return_message(get_lang('Deleted')));
header('Location: '.api_get_self());
exit;
break;
}
if (api_is_platform_admin()) {
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Add'),
api_get_path(WEB_PLUGIN_PATH).'justification/add.php',
'plus',
'primary'
);
}
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Users'),
api_get_path(WEB_PLUGIN_PATH).'justification/justification_by_user.php',
'user',
'primary'
);
if (api_is_platform_admin()) {
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('SetNewCourse'),
api_get_path(WEB_PLUGIN_PATH).'justification/set_course.php',
'book',
'primary'
);
}
$tpl->assign(
'actions',
Display::toolbarAction('toolbar', [$actionLinks])
);
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,6 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
$plugin_info = Justification::create()->get_info();

View File

@@ -0,0 +1,57 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$tool = 'justification';
$plugin = Justification::create();
$tpl = new Template($tool);
$fields = [];
$form = new FormValidator('add');
$form->addHeader($plugin->get_lang('SetNewCourse'));
$currentCourse = api_get_setting('justification_default_course_id', 'justification');
if (!empty($currentCourse)) {
$courseInfo = api_get_course_info_by_id($currentCourse);
Display::addFlash(Display::return_message(get_lang('Course').': '.$courseInfo['title']));
}
$form->addSelectAjax(
'course_id',
get_lang('Course'),
null,
[
'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_course',
]
);
$form->addButtonSave(get_lang('Save'));
if ($form->validate()) {
$values = $form->getSubmitValues();
api_set_setting('justification_default_course_id', $values['course_id']);
Display::addFlash(Display::return_message(get_lang('Saved')));
$url = api_get_path(WEB_PLUGIN_PATH).'justification/list.php?';
header('Location: '.$url);
exit;
}
$actionLinks = Display::toolbarButton(
$plugin->get_lang('Back'),
api_get_path(WEB_PLUGIN_PATH).'justification/list.php',
'arrow-left',
'primary'
);
$tpl->assign(
'actions',
Display::toolbarAction('toolbar', [$actionLinks])
);
$content = $form->returnForm();
$tpl->assign('content', $content);
$tpl->display_one_col_template();

View File

@@ -0,0 +1,8 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
Justification::create()->uninstall();

View File

@@ -0,0 +1,48 @@
{{ search_form }}
<table class="table table-hover table-striped">
<thead>
<tr>
<th>{{ 'CreatedAt'|get_lang }}</th>
<th>{{ 'Status'|get_lang }}</th>
<th>{{ 'Records'|get_plugin_lang('BBBPlugin') }}</th>
<th>{{ 'Course'|get_lang }}</th>
<th>{{ 'Session'|get_lang }}</th>
<th>{{ 'Participants'|get_lang }}</th>
<th>{{ 'Actions'|get_lang }}</th>
</tr>
</thead>
<tbody>
{% for meeting in meetings %}
<tr id="meeting-{{ meeting.id }}">
{% if meeting.visibility == 0 %}
<td class="muted">{{ meeting.created_at }}</td>
{% else %}
<td>{{ meeting.created_at }}</td>
{% endif %}
<td>
{% if meeting.status == 1 %}
<span class="label label-success">{{ 'MeetingOpened'|get_plugin_lang('BBBPlugin') }}</span>
{% else %}
<span class="label label-info">{{ 'MeetingClosed'|get_plugin_lang('BBBPlugin') }}</span>
{% endif %}
</td>
<td>
{% if meeting.record == 1 %}
{# Record list #}
{{ meeting.show_links }}
{% else %}
{{ 'NoRecording'|get_plugin_lang('BBBPlugin') }}
{% endif %}
</td>
<td>{{ meeting.course ?: '-' }}</td>
<td>{{ meeting.session ?: '-' }}</td>
<td>
{{ meeting.participants ? meeting.participants|join('<br>') : '-' }}
</td>
<td>
{{ meeting.action_links }}
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -0,0 +1,38 @@
{{ form }}
{% if list %}
<div class ="row">
<div class ="col-md-12">
<div class="page-header">
<h2>{{ 'DocumentListForUserX'| get_plugin_lang('Justification')|format(user_info.complete_name) }}</h2>
</div>
<table class="table">
<tr>
<th>{{ 'Justification'| get_plugin_lang('Justification') }}</th>
<th>{{ 'File'| get_lang }}</th>
<th>{{ 'Date'| get_lang('Date') }}</th>
<th>{{ 'Actions'| get_lang }}</th>
</tr>
{% for item in list %}
<tr>
<td >{{ item.justification.name }} </td>
<td >{{ item.file_path }} </td>
<td >
{{ item.date_validity }}
</td>
<td>
<a href="{{_p.web_plugin }}justification/justification_by_user.php?a=edit&user_id={{ user_id }}&id={{ item.id }}"
class="btn btn-primary">
{{'Edit' | get_lang}}
</a>
<a href="{{_p.web_plugin }}justification/justification_by_user.php?a=delete&user_id={{ user_id }}&id={{ item.id }}"
class="btn btn-danger">
{{'Delete' | get_lang}}
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,33 @@
<div class ="row">
<div class ="col-md-12">
<div class="page-header">
<h2>{{ 'List'| get_lang }}</h2>
</div>
<table class="table">
<tr>
<th>{{ 'Name'| get_lang }}</th>
<th>{{ 'ValidityDuration'| get_plugin_lang('Justification') }}</th>
<th>{{ 'DateManualOn'| get_plugin_lang('Justification') }}</th>
<th>{{ 'Actions'| get_lang }}</th>
</tr>
{% for item in list %}
<tr>
<td >{{ item.name }} ({{ item.code }})</td>
<td >{{ item.validity_duration }}</td>
<td >{{ item.date_manual_on }}</td>
<td>
<a href="{{_p.web_plugin }}justification/edit.php?id={{ item.id }}" class="btn btn-primary">
{{'Edit' | get_lang}}
</a>
<a href="{{_p.web_plugin }}justification/list.php?a=delete&id={{ item.id }}" class="btn btn-danger">
{{'Delete' | get_lang}}
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>