HtmlRenderer
📦 HtmlRenderer
HTML Renderer for CalDAV Calendar Interface This class handles the rendering of the calendar's HTML interface, including: - Calendar grid and navigation - Event creation/editing modals - Calendar list and filters - Event management UI components The renderer uses Toast UI Calendar for the frontend calendar widget and provides a responsive, modern interface for calendar management.
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
🔧 __construct
Constructor
function __construct($serverCalendars, $initialEvents, $extsite_www_path, $caldav_config, $readOnly = false, $datas = []) {
$this->serverCalendars = $serverCalendars;
$this->initialEvents = $initialEvents;
$this->extsite_www_path = $extsite_www_path;
$this->readOnly = $readOnly;
$this->datas = $datas;
// Transform the config structure to match what CalDavEventManager expects
$this->caldav_config = [
'url' => $caldav_config['caldav']['base_url'],
'username' => $caldav_config['caldav']['admin_username'],
'password' => $caldav_config['caldav']['admin_password']
// ... (truncated)
⚙️ Parameters
$serverCalendars (array) List of available calendars
$initialEvents (array) Initial events to display
$extsite_www_path (string) Path to external resources
$caldav_config (array) CalDAV configuration
🔧 createCalDavCalendarManagerTest
Create Calendar Manager Test Instance Factory method for creating a test instance of the calendar manager
function createCalDavCalendarManagerTest($caldav_config) {
$calendarManager = new CalDavCalendarManager(
$caldav_config['url'],
$caldav_config['username'],
$caldav_config['password'],
$caldav_config
);
return new CalDavCalendarManagerTest($calendarManager);
}
⚙️ Parameters
$caldav_config (array) Configuration for the test instance
↩️ Returns
(CalDavCalendarManagerTest) Test instance
🔧 createCalDavUserManagerTest
Create User Manager Test Instance Factory method for creating a test instance of the user manager
function createCalDavUserManagerTest($caldav_config) {
$userManager = new \CalDav\Client\CalDavUserManager(
$caldav_config['url'],
$caldav_config['username'],
$caldav_config['password'],
$caldav_config
);
return new CalDavUserManagerTest($userManager);
}
⚙️ Parameters
$caldav_config (array) Configuration for the test instance
↩️ Returns
(CalDavUserManagerTest) Test instance
🔧 actionHandler
Handle AJAX Actions Processes all AJAX requests for calendar operations including: - Creating events - Updating events - Deleting events - Running tests
function actionHandler() {
// Add this after your other PHP code but before the HTML/JavaScript
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
ob_clean();
try {
// Check if in read-only mode and prevent modifications
if ($this->readOnly && in_array($_POST['action'], ['createEvent', 'updateEvent', 'deleteEvent'])) {
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'message' => 'Calendar is in read-only mode. Modifications are not allowed.'
]);
// ... (truncated)
↩️ Returns
(void)
🔧 renderHtml
Render Calendar Interface Renders the complete calendar interface including: - Calendar grid - Navigation controls - Event modals - Calendar list - Testing tools
function renderHtml() {
$this->actionHandler();
?>
<link rel="stylesheet" href="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/toastui-calendar.min.css">
<link rel="stylesheet" href="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/tui-date-picker.css">
<link rel="stylesheet" href="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/tui-time-picker.css">
<script src="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/toastui-calendar.min.js"></script>
<script src="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/tui-date-picker.min.js"></script>
<script src="<?php echo $this->extsite_www_path; ?>lib/toastui-calendar/tui-time-picker.min.js"></script>
<style>
#calendar {
width: 100%;
height: 800px;
}
.lnb-calendars-item {
display: inline-block;
margin-right: 15px;
}
#calendarList {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
}
.checkbox-wrapper {
display: inline-flex;
align-items: center;
cursor: pointer;
white-space: nowrap;
}
.checkbox-wrapper input[type="checkbox"] {
display: none;
}
.checkbox-custom {
width: 18px;
height: 18px;
border: 2px solid #ddd;
border-radius: 3px;
display: inline-block;
position: relative;
margin-right: 5px;
}
.checkbox-wrapper input[type="checkbox"]:checked + .checkbox-custom::after {
content: '\2714';
position: absolute;
top: 0;
left: 2px;
color: #333;
}
.checkbox-label {
font-size: 14px;
color: #333;
}
#menu .eg_btn {
color: #333;
border: 1px solid #ced4da;
padding: 8px 12px;
margin-right: 5px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
}
#menu .eg_btn:hover,
#menu .eg_btn.active {
background-color: #e9ecef;
border-color: #ced4da;
}
#menu .eg_btn.theme-light {
background-color: #ffffff;
color: #333;
}
#menu .eg_btn.theme-grey {
background-color: #f0f0f0;
color: #333;
}
#menu .eg_btn.theme-dark {
background-color: #343a40;
color: #ffffff;
}
#menu .eg_btn.theme-light {
background-color: #ffffff;
color: #333;
}
#menu .eg_btn.theme-grey {
background-color: #f0f0f0;
color: #333;
}
#menu .eg_btn.theme-dark {
background-color: #343a40;
color: #ffffff;
}
#renderRange {
font-size: 16px;
font-weight: bold;
color: #495057;
}
.btn-group-view{
float: right;
}
.toastui-calendar-weekday-grid-date-decorator {
background-color: #343a40 !important;
}
.form-group {
margin-bottom: 1rem;
}
.form-control {
display: block;
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.form-control:focus {
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
/* Updated modal styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
backdrop-filter: blur(3px);
}
.modal-content {
background-color: #ffffff;
margin: 5% auto;
padding: 30px;
border: none;
border-radius: 12px;
width: 500px;
max-width: 50%;
position: relative;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
animation: modalSlideIn 0.3s ease-out;
}
@keyframes modalSlideIn {
from {
transform: translateY(-20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.close {
position: absolute;
right: 20px;
top: 15px;
color: #666;
font-size: 28px;
font-weight: 300;
cursor: pointer;
transition: color 0.2s ease;
line-height: 1;
}
.close:hover,
.close:focus {
color: #000;
}
/* Enhanced form elements */
.modal .form-group {
margin-bottom: 1.2rem;
}
.modal .form-control {
padding: 0.6rem 1rem;
border: 2px solid #e0e0e0;
border-radius: 8px;
transition: all 0.2s ease;
font-size: 0.95rem;
}
.modal .form-control:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
}
.modal textarea.form-control {
min-height: 100px;
resize: vertical;
}
/* Modal title styling */
.modal h2 {
margin-top: 0;
margin-bottom: 1.5rem;
padding-right: 25px;
font-size: 1.5rem;
color: #333;
font-weight: 600;
}
/* Submit button styling */
.modal .eg_btn[type="submit"] {
background-color: #4a90e2;
color: white;
padding: 0.8rem 1.5rem;
border: none;
border-radius: 8px;
font-weight: 500;
width: 100%;
margin-top: 1rem;
transition: all 0.2s ease;
}
.modal .eg_btn[type="submit"]:hover {
background-color: #357abd;
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(74, 144, 226, 0.2);
}
/* Label styling */
.modal label {
color: #555;
font-weight: 500;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
/* Event details styling */
#eventTime, #eventDescription {
color: #666;
line-height: 1.6;
margin: 0.5rem 0;
}
/* Event display modal styles */
.event-modal {
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(4px);
}
.event-modal .modal-content {
background-color: #ffffff;
margin: 40px auto;
padding: 0;
border: none;
border-radius: 16px;
width: 400px;
max-width: 30%;
position: relative;
box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14);
animation: modalSlideIn 0.25s ease-out;
}
.event-modal .modal-header {
padding: 20px 24px;
border-bottom: 1px solid #f1f3f4;
background-color: #f8f9fa;
border-radius: 16px 16px 0 0;
}
.event-modal .event-title {
font-size: 20px;
font-weight: 500;
color: #202124;
margin: 0;
padding-right: 32px;
}
.event-modal .modal-body {
padding: 20px 24px;
}
.event-modal .event-info {
display: flex;
align-items: center;
margin-bottom: 16px;
gap: 16px;
}
.event-modal .event-info-icon {
color: #5f6368;
font-size: 20px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.event-modal .event-info-content {
flex: 1;
color: #3c4043;
font-size: 14px;
line-height: 20px;
display: flex;
align-items: center;
min-height: 24px;
}
.event-modal .event-time {
font-weight: 500;
color: #1a73e8;
}
.event-modal .event-description {
color: #5f6368;
font-size: 14px;
line-height: 1.5;
white-space: pre-wrap;
margin-top: 16px;
padding: 12px;
background-color: #f8f9fa;
border-radius: 8px;
}
.entity-link-badge {
display: inline-flex;
align-items: center;
padding: 4px 8px;
background-color: #e8f0fe;
color: #1967d2;
font-size: 13px;
font-weight: 500;
border-radius: 16px;
margin: 4px 0;
}
.entity-link-badge i {
margin-right: 6px;
}
.event-modal .close {
position: absolute;
right: 12px;
top: 12px;
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #5f6368;
font-size: 20px;
cursor: pointer;
transition: all 0.2s;
background-color: transparent;
}
.event-modal .close:hover {
background-color: #e8eaed;
}
.event-actions {
margin-top: 20px;
display: flex;
gap: 10px;
justify-content: flex-end;
}
.btn-edit {
background-color: #4a90e2;
color: white;
}
.btn-delete {
background-color: #dc3545;
color: white;
}
.event-actions .eg_btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
gap: 5px;
}
.event-actions .eg_btn:hover {
opacity: 0.9;
}
.location-search-container {
position: relative;
}
.location-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid #ddd;
border-radius: 4px;
max-height: 200px;
overflow-y: auto;
z-index: 1000;
display: none;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.location-result-item {
padding: 8px 12px;
cursor: pointer;
border-bottom: 1px solid #eee;
}
.location-result-item:hover {
background-color: #f5f5f5;
}
</style>
<div id="lnb">
<div id="lnb-calendars" class="lnb-calendars">
<div class="d-flex flex-wrap align-items-center mb-3">
<div class="lnb-calendars-item mr-3">
<label class="checkbox-wrapper">
<input class="tui-full-calendar-checkbox-square" type="checkbox" value="all" checked>
<span class="checkbox-custom"></span>
<span class="checkbox-label">Voir tout</span>
</label>
</div>
<div id="calendarList" class="d-flex flex-wrap">
</div>
</div>
</div>
</div>
<div id="menu" class="mb-3">
<span id="menu-navi" class="btn-group mr-2">
<button type="button" class="eg_btn" id="today">Aujourd'hui</button>
<button type="button" class="eg_btn" id="prev">
<i class="fas fa-chevron-left"></i> Précédent
</button>
<span id="renderRange" class="render-range mr-3"></span>
<button type="button" class="eg_btn" id="next">
Suivant <i class="fas fa-chevron-right"></i>
</button>
</span>
<div class="btn-group btn-group-view" role="group" aria-label="Vue du calendrier">
<button type="button" class="eg_btn" data-view="day">Jour</button>
<button type="button" class="eg_btn" data-view="week">Semaine</button>
<button type="button" class="eg_btn active" data-view="month">Mois</button>
</div>
</div>
<div id="calendar"></div>
<div id="eventDisplayModal" class="modal event-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="event-title" id="h3eventTitle"></h3>
<span class="close">×</span>
</div>
<div class="modal-body">
<div class="event-info">
<div class="event-info-icon">
<i class="fas fa-calendar"></i>
</div>
<div class="event-info-content">
<div class="event-time" id="eventTime"></div>
</div>
</div>
<div class="event-info">
<div class="event-info-icon"><i class="fas fa-pen"></i></div>
<div class="event-info-content">
<div class="event-description" id="displayEventDescription"></div>
</div>
</div>
<div class="event-info">
<strong>Localisation:</strong>
<span id="eventLocation"></span>
</div>
<div class="event-info">
<strong>Calendrier:</strong>
<div id="eventCalendarName"></div>
</div>
<!-- Add entity link indicator -->
<div class="event-info" id="eventEntityLink" style="display: none;">
<div class="event-info-icon"><i class="fas fa-link"></i></div>
<div class="event-info-content">
<div class="entity-link-badge">
<span id="entityLinkType"></span>
<span id="entityLinkId"></span>
</div>
</div>
</div>
<!-- Add action buttons -->
<div class="event-actions">
<button class="eg_btn btn-edit" id="editEventBtn">
<i class="fas fa-edit"></i> Modifier
</button>
<button class="eg_btn btn-delete" id="deleteEventBtn">
<i class="fas fa-trash"></i> Supprimer
</button>
</div>
</div>
</div>
</div>
<?php if (!$this->readOnly): ?>
<div id="createEventModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<h2>Créer un événement</h2>
<form id="createEventForm">
<div class="form-group mb-3">
<label for="eventCategory">Type</label>
<select id="eventCategory" class="form-control" required>
<option value="time">Événement</option>
<option value="allday">Toute la journée</option>
<option value="milestone">Jalon</option>
<option value="task">Tâche</option>
</select>
</div>
<div class="form-group mb-3">
<label for="eventTitle">Titre</label>
<input type="text" id="eventTitle" class="form-control" required>
</div>
<div id="timeInputs">
<div class="form-group mb-3">
<label for="eventStart">Début</label>
<input type="datetime-local" id="eventStart" class="form-control" required>
</div>
<div class="form-group mb-3" id="endTimeGroup">
<label for="eventEnd">Fin</label>
<input type="datetime-local" id="eventEnd" class="form-control" required>
</div>
</div>
<div class="form-group mb-3">
<label for="eventCalendar">Calendar</label>
<select id="eventCalendar" class="form-control" required>
<?php if (!empty($this->serverCalendars)): ?>
<?php foreach ($this->serverCalendars as $calendar): ?>
<option value="<?php echo $calendar['href']; ?>">
<?php echo htmlspecialchars($calendar['name']); ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="form-group mb-3">
<label for="entityData">Données existantes</label>
<select id="entityData" class="form-control">
<option value="">Sélectionner une donnée</option>
<?php if (!empty($this->datas['opportunites'])): ?>
<optgroup label="Opportunités">
<?php foreach ($this->datas['opportunites'] as $opportunite): ?>
<option value="opportunite_<?php echo $opportunite->getAttributeidobje(); ?>">
<?php echo htmlspecialchars(empty($opportunite->getCalendarEventData()["title"]) ? "Opportunité sans titre #".$opportunite->getAttributeidobje() : $opportunite->getCalendarEventData()["title"]); ?>
</option>
<?php endforeach; ?>
</optgroup>
<?php endif; ?>
<?php if (!empty($this->datas['commandes'])): ?>
<optgroup label="Commandes">
<?php foreach ($this->datas['commandes'] as $commande): ?>
<option value="commande_<?php echo $commande->getIdobjet(); ?>">
<?php echo htmlspecialchars(empty($commande->getCalendarEventData()["title"]) ? "Commande sans titre #".$commande->getIdobjet() : $commande->getCalendarEventData()["title"]); ?>
</option>
<?php endforeach; ?>
</optgroup>
<?php endif; ?>
</select>
</div>
<div class="form-group mb-3">
<label for="eventDescription">Description</label>
<textarea id="createEventDescription" class="form-control" rows="3"></textarea>
</div>
<div class="form-group mb-3">
<label for="createEventLocation">Localisation</label>
<div class="location-search-container">
<input type="text"
class="form-control"
id="createEventLocation"
name="eventLocation"
placeholder="Rechercher une adresse..."
autocomplete="off">
<div id="createLocationResults" class="location-results"></div>
</div>
</div>
<!-- Hidden fields to track selected entity -->
<input type="hidden" id="selectedEntityId" name="selectedEntityId" value="">
<input type="hidden" id="selectedEntityType" name="selectedEntityType" value="">
<button type="submit" class="eg_btn">Créer l'événement</button>
</form>
</div>
</div>
<?php endif; ?>
<!-- Add edit modal -->
<?php if (!$this->readOnly): ?>
<div id="editEventModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<h2>Modifier l'événement</h2>
<form id="editEventForm">
<input type="hidden" id="editEventId">
<div class="form-group mb-3">
<label for="editEventCategory">Type</label>
<select id="editEventCategory" class="form-control" required>
<option value="time">Événement</option>
<option value="allday">Toute la journée</option>
<option value="milestone">Jalon</option>
<option value="task">Tâche</option>
</select>
</div>
<div class="form-group mb-3">
<label for="editEventTitle">Titre</label>
<input type="text" id="editEventTitle" class="form-control" required>
</div>
<div class="form-group mb-3">
<label for="editEventStart">Début</label>
<input type="datetime-local" id="editEventStart" class="form-control" required>
</div>
<div class="form-group mb-3">
<label for="editEventEnd">Fin</label>
<input type="datetime-local" id="editEventEnd" class="form-control" required>
</div>
<div class="form-group mb-3">
<label for="editEventCalendar">Calendrier</label>
<select id="editEventCalendar" class="form-control" required>
<?php foreach ($this->serverCalendars as $calendar): ?>
<option value="<?php echo $calendar['href']; ?>">
<?php echo htmlspecialchars($calendar['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group mb-3">
<label for="editEventDescription">Description</label>
<textarea id="editEventDescription" class="form-control" rows="3"></textarea>
</div>
<div class="form-group mb-3">
<label for="editEventLocation">Localisation</label>
<div class="location-search-container">
<input type="text" class="form-control" id="editEventLocation" name="editEventLocation" placeholder="Rechercher une adresse..." autocomplete="off">
<div id="editLocationResults" class="location-results"></div>
</div>
</div>
<div class="form-group mb-3" id="editEventEntityLink" style="display: none;">
<div class="entity-link-badge">
<i class="fas fa-link"></i>
<span id="editEntityLinkType"></span>
<span id="editEntityLinkId"></span>
</div>
</div>
<button type="submit" class="eg_btn">Enregistrer</button>
</form>
</div>
</div>
<?php endif; ?>
<!-- Add this HTML for the delete confirmation modal -->
<?php if (!$this->readOnly): ?>
<div id="deleteConfirmModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3>Confirmation de suppression</h3>
<span class="close">×</span>
</div>
<div class="modal-body">
<p>Êtes-vous sûr de vouloir supprimer cet événement ?</p>
<div class="event-actions">
<button class="eg_btn" id="cancelDelete">Annuler</button>
<button class="eg_btn btn-delete" id="confirmDelete">Supprimer</button>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php
}
↩️ Returns
(void)
🔧 updateLinkedEntityDates
Update the dates of a linked entity when an event is edited
function updateLinkedEntityDates($eventId, $eventUrl, $startDate, $endDate) {
try {
// Helper function to find entity by calendar event ID
$findEntityByCalendarEventId = function($entityClass, $eventId) {
$entities = (new $entityClass())->findBy(['Calendarevent' => '%'.$eventId.'%']);
return !empty($entities) ? $entities[0] : null;
};
// Try to find an opportunity first
$opportunite = $findEntityByCalendarEventId(\CalDav\Entity\Opportunite::class, $eventId);
if ($opportunite) {
// Update DateDeProchainRappel and Daterdvtechnique for Opportunite entities
// Format for Opportunite needs to be YYYYMMDDHHmm (12 characters)
$opportunite->setDaterdvtechnique($startDate->format('YmdHi'));
// Update the Calendarevent field with the new event URL
$opportunite->setCalendarevent($eventUrl);
// ... (truncated)
⚙️ Parameters
$eventId (string) The ID of the event being edited
$startDate (\DateTime) The new start date of the event
$endDate (\DateTime) The new end date of the event
↩️ Returns
(bool) True if an entity was updated, false otherwise