Compare commits

...
2 Commits
16 changed files with 1401 additions and 3 deletions

No files matched your search

+1 -1
View File
@@ -21,4 +21,4 @@ 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 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/> For more information, please refer to <https://unlicense.org/>
+4 -2
View File
@@ -3,13 +3,15 @@
Module Agenda associatif pour le logiciel Paheko Module Agenda associatif pour le logiciel Paheko
## Fonctionnalités ## Fonctionnalités
+ Calendrier mensuel/semaine/liste, + gestion de plusieurs calendriers (couleurs et catégorie),
+ catégorie : accès public, membres, administrateurs
+ vues : mensuel/semaine/liste,
+ rendez-vous réguliers récurrents (avec exceptions et couleurs), + rendez-vous réguliers récurrents (avec exceptions et couleurs),
+ événements ponctuels, + événements ponctuels,
+ purge et tri automatiques. + purge et tri automatiques.
## Installation ## Installation
Via module dans Paheko Via import module dans Paheko
## License ## License
Libre de tout droit Libre de tout droit
+48
View File
@@ -0,0 +1,48 @@
{{if $est_admin}}
<div class="card card-perm">
<h2>Rendez-vous réguliers</h2>
{{:assign var="perm_trouve" value=false}}
<div class="scroll-cal">
<table class="permanences">
<thead><tr><th>Récurrence</th><th>Jour</th><th>Horaires</th><th>Détail</th><th>Lieu</th><th>Calendrier</th><th>Depuis / jusqu'à</th>{{if $est_admin}}<th></th>{{/if}}</tr></thead>
<tbody>
{{#load where="$$.type = 'permanence'" order="$$.jour ASC, $$.debut ASC"}}
{{:assign var="perm_trouve" value=true}}
{{:assign var="nom_jour" from="noms_jours.%s"|args:$jour}}
<tr>
<td>
{{if $type_recurrence == "mensuel"}}
{{if $semaine_du_mois == -1}}Dernier{{elseif $semaine_du_mois == 1}}1er{{else}}{{$semaine_du_mois}}e{{/if}} du mois
{{elseif $type_recurrence == "quinzaine"}}
Toutes les 2 semaines
{{else}}
Chaque semaine
{{/if}}
</td>
<td>{{$nom_jour}}</td>
<td>{{$debut}}{{if $fin}} — {{$fin}}{{/if}}</td>
<td>{{$label}}</td>
<td>{{if $lieu}}<a class="lieu-lien" href="https://www.openstreetmap.org/search?query={{$lieu|url_encode}}" target="_blank" rel="noopener">{{$lieu}}</a>{{/if}}</td>
<td>
{{:assign var="cal_eff_tab" value=$calendrier}}
{{if $cal_eff_tab == ""}}{{:assign var="cal_eff_tab" value="agenda"}}{{/if}}
{{:assign var="nom_cal_tab" from="calendriers_liste.%s.nom"|args:$cal_eff_tab}}
{{$nom_cal_tab}}
</td>
<td>{{if $date_debut}}à partir du {{$date_debut|date_short}}{{/if}}{{if $date_debut && $date_fin}}<br />{{/if}}{{if $date_fin}}jusqu'au {{$date_fin|date_short}}{{/if}}</td>
{{if $est_admin}}
<td>
<a class="mini" href="index.html?edit_perm={{$id}}#form-perm" title="Modifier">&#9998;</a>
<form method="post" action="index.html" style="display:inline">
<button type="submit" name="suppr_perm" value="{{$id}}" class="mini" title="Supprimer">&#10005;</button>
</form>
</td>
{{/if}}
</tr>
{{/load}}
</tbody>
</table>
</div>
{{if !$perm_trouve}}<p class="vide">Aucun rendez-vous régulier enregistré.</p>{{/if}}
</div>
{{/if}}
+189
View File
@@ -0,0 +1,189 @@
{{if $vue != "liste"}}
<div class="card">
<h2 style="background:hsl({{$selected_calendar_couleur}},100%,50%)">Calendrier ({{$selected_calendar_name}})</h2>
{{if $vue == "mois"}}
<div class="nav-mois">
<a href="{{$_url}}?vue=mois&amp;an={{$an_prec}}&amp;mois={{$mois_prec}}">&larr;</a>
<span>{{$nom_mois}}</span>
<a href="{{$_url}}?vue=mois&amp;an={{$an_suiv}}&amp;mois={{$mois_suiv}}">&rarr;</a>
</div>
{{else}}
<div class="nav-mois">
{{if $semaine_sel <= 1}}
<a href="{{$_url}}?vue=semaine&amp;an={{$an_prec}}&amp;mois={{$mois_prec}}&amp;semaine_sel={{$total_rows_prec}}">&larr;</a>
{{else}}
<a href="{{$_url}}?vue=semaine&amp;an={{$an}}&amp;mois={{$mois}}&amp;semaine_sel={{"%d-1"|math:$semaine_sel}}">&larr;</a>
{{/if}}
<span>Semaine du {{$nom_mois}}</span>
{{if $semaine_sel >= $total_rows}}
<a href="{{$_url}}?vue=semaine&amp;an={{$an_suiv}}&amp;mois={{$mois_suiv}}&amp;semaine_sel=1">&rarr;</a>
{{else}}
<a href="{{$_url}}?vue=semaine&amp;an={{$an}}&amp;mois={{$mois}}&amp;semaine_sel={{"%d+1"|math:$semaine_sel}}">&rarr;</a>
{{/if}}
</div>
{{/if}}
<div class="scroll-cal">
<table class="calendrier">
<thead>
<tr><th>Lun</th><th>Mar</th><th>Mer</th><th>Jeu</th><th>Ven</th><th>Sam</th><th>Dim</th></tr>
</thead>
<tbody>
<tr>
{{#foreach count=42 key="i"}}
{{:assign var="i" value="1+%d"|math:$i}}
{{:assign var="cellules." value=$i}}
{{/foreach}}
{{*
{{:assign var="cellules." value=1}}{{:assign var="cellules." value=2}}{{:assign var="cellules." value=3}}{{:assign var="cellules." value=4}}{{:assign var="cellules." value=5}}{{:assign var="cellules." value=6}}{{:assign var="cellules." value=7}}{{:assign var="cellules." value=8}}{{:assign var="cellules." value=9}}{{:assign var="cellules." value=10}}
{{:assign var="cellules." value=11}}{{:assign var="cellules." value=12}}{{:assign var="cellules." value=13}}{{:assign var="cellules." value=14}}{{:assign var="cellules." value=15}}{{:assign var="cellules." value=16}}{{:assign var="cellules." value=17}}{{:assign var="cellules." value=18}}{{:assign var="cellules." value=19}}{{:assign var="cellules." value=20}}
{{:assign var="cellules." value=21}}{{:assign var="cellules." value=22}}{{:assign var="cellules." value=23}}{{:assign var="cellules." value=24}}{{:assign var="cellules." value=25}}{{:assign var="cellules." value=26}}{{:assign var="cellules." value=27}}{{:assign var="cellules." value=28}}{{:assign var="cellules." value=29}}{{:assign var="cellules." value=30}}
{{:assign var="cellules." value=31}}{{:assign var="cellules." value=32}}{{:assign var="cellules." value=33}}{{:assign var="cellules." value=34}}{{:assign var="cellules." value=35}}{{:assign var="cellules." value=36}}{{:assign var="cellules." value=37}}{{:assign var="cellules." value=38}}{{:assign var="cellules." value=39}}{{:assign var="cellules." value=40}}
{{:assign var="cellules." value=41}}{{:assign var="cellules." value=42}}
*}}
{{#foreach from=$cellules item="n"}}
{{:assign var="rangee_n" value="floor((%d-1)/7)+1"|math:$n}}
{{if $vue == "mois" || $rangee_n == $semaine_sel}}
{{:assign var="jour_num" value="%d-%d"|math:$n:$decalage}}
{{if $jour_num >= 1 && $jour_num <= $nb_jours}}
{{:assign var="date_cellule" value="%04d-%02d-%02d"|args:$an:$mois:$jour_num}}
{{:assign var="dow_cellule" value=$date_cellule|date:"N"}}
{{:assign var="occurrence_mois" value="floor((%d-1)/7)+1"|math:$jour_num}}
{{:assign var="est_derniere_occurrence" value=false}}
{{if "%d+7"|math:$jour_num > $nb_jours}}{{:assign var="est_derniere_occurrence" value=true}}{{/if}}
{{:assign var="evts_ce_jour" from="events_par_jour.%s"|args:$date_cellule}}
{{:assign var="badges_jour" value=""}}
{{#foreach from=$perms_data item="pd"}}
{{if $pd.jour == $dow_cellule}}
{{if $pd.date_debut == "" || $date_cellule >= $pd.date_debut}}
{{if $pd.date_fin == "" || $date_cellule <= $pd.date_fin}}
{{:assign var="est_exclue" value=false}}
{{#foreach from=$pd.exceptions item="ex"}}
{{if $ex == $date_cellule}}{{:assign var="est_exclue" value=true}}{{/if}}
{{/foreach}}
{{if !$est_exclue}}
{{:assign var="afficher_badge" value=false}}
{{if $pd.type_recurrence == "mensuel"}}
{{if $pd.semaine_du_mois == -1 && $est_derniere_occurrence}}{{:assign var="afficher_badge" value=true}}{{/if}}
{{if $pd.semaine_du_mois == $occurrence_mois}}{{:assign var="afficher_badge" value=true}}{{/if}}
{{elseif $pd.type_recurrence == "quinzaine"}}
{{if $pd.date_debut != ""}}
{{:assign var="ref_sem_q" value=$pd.date_debut|date:"W"|intval}}
{{:assign var="cell_sem_q" value=$date_cellule|date:"W"|intval}}
{{:assign var="diff_sem_q" value="(%d-%d) %% 2"|math:$cell_sem_q:$ref_sem_q}}
{{if $diff_sem_q == 0}}{{:assign var="afficher_badge" value=true}}{{/if}}
{{/if}}
{{else}}
{{:assign var="afficher_badge" value=true}}
{{/if}}
{{if $afficher_badge}}
{{:assign var="cle_b" value="%s_a_perm%s"|args:$pd.debut:$pd.id}}
{{:assign var="badges_jour.%s.type"|args:$cle_b value="perm"}}
{{:assign var="badges_jour.%s.debut"|args:$cle_b value=$pd.debut}}
{{:assign var="badges_jour.%s.fin"|args:$cle_b value=$pd.fin}}
{{:assign var="badges_jour.%s.label"|args:$cle_b value=$pd.label}}
{{:assign var="badges_jour.%s.couleur"|args:$cle_b value=$pd.couleur|or:'#4c7a2e'}}
{{:assign var="badges_jour.%s.pid"|args:$cle_b value=$pd.id}}
{{:assign var="badges_jour.%s.lieu"|args:$cle_b value=$pd.lieu}}
{{:assign var="badges_jour.%s.description"|args:$cle_b value=$pd.description}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/foreach}}
{{if $evts_ce_jour}}
{{#foreach from=$evts_ce_jour item="ev"}}
{{:assign var="cle_b" value="%s_b_evt%s"|args:$ev.debut:$ev.id}}
{{:assign var="badges_jour.%s.type"|args:$cle_b value="evt"}}
{{:assign var="badges_jour.%s.id"|args:$cle_b value=$ev.id}}
{{:assign var="badges_jour.%s.debut"|args:$cle_b value=$ev.debut}}
{{:assign var="badges_jour.%s.fin"|args:$cle_b value=$ev.fin}}
{{:assign var="badges_jour.%s.label"|args:$cle_b value=$ev.titre}}
{{:assign var="badges_jour.%s.couleur"|args:$cle_b value=$ev.couleur|or:'#8c3a1e'}}
{{:assign var="badges_jour.%s.lieu"|args:$cle_b value=$ev.lieu}}
{{:assign var="badges_jour.%s.description"|args:$cle_b value=$ev.description}}
{{:assign var="badges_jour.%s.lien"|args:$cle_b value=$ev.lien}}
{{:assign var="badges_jour.%s.lien1_label"|args:$cle_b value=$ev.lien1_label}}
{{:assign var="badges_jour.%s.lien1_url"|args:$cle_b value=$ev.lien1_url}}
{{:assign var="badges_jour.%s.lien2_label"|args:$cle_b value=$ev.lien2_label}}
{{:assign var="badges_jour.%s.lien2_url"|args:$cle_b value=$ev.lien2_url}}
{{:assign var="badges_jour.%s.lien3_label"|args:$cle_b value=$ev.lien3_label}}
{{:assign var="badges_jour.%s.lien3_url"|args:$cle_b value=$ev.lien3_url}}
{{/foreach}}
{{/if}}
{{if $badges_jour}}
{{:assign var="badges_tries" value=$badges_jour|ksort|values}}
{{else}}
{{:assign var="badges_tries" value=""}}
{{/if}}
<td{{if $date_cellule == $aujourdhui}} class="today"{{/if}}>
<div class="num">{{$jour_num}}</div>
{{#foreach from=$badges_tries item="bj"}}
{{if $bj.type == "perm"}}
<div class="perm-badge" style="background:{{$bj.couleur}};">
<div class="badge-content" onclick="ouvrirDetailEvt(this);" data-titre="{{$bj.label}}" data-horaire="{{if $bj.debut}}{{$bj.debut}}{{if $bj.fin}}–{{$bj.fin}}{{/if}}{{/if}}" data-lieu="{{$bj.lieu}}" data-description="{{$bj.description}}" data-lien1-label="" data-lien1-url="" data-lien2-label="" data-lien2-url="" data-lien3-label="" data-lien3-url="">
{{if $bj.debut}}{{$bj.debut}}{{if $bj.fin}}–{{$bj.fin}}{{/if}} — {{/if}}{{$bj.label}}{{if $bj.lieu}}<br /><a class="lieu-lien" href="https://www.openstreetmap.org/search?query={{$bj.lieu|url_encode}}" target="_blank" rel="noopener" onclick="event.stopPropagation();">&#128205; {{$bj.lieu}}</a>{{/if}}
{{if $bj.description}}<div class="evt-desc-apercu">{{$bj.description}}</div>{{/if}}
</div>
{{if $est_admin}}
<span class="badge-actions">
<a class="badge-edit" href="index.html?edit_perm={{$bj.pid}}#form-perm" title="Modifier" onclick="event.stopPropagation();">&#9998;</a>
<form method="post" action="" class="mini-form" onclick="event.stopPropagation();">
{{:input type="hidden" name="perm_id" default=$bj.pid }}
{{:input type="hidden" name="date_exclue" default=$date_cellule }}
{{:input type="hidden" name="retour_an" default=$an }}
{{:input type="hidden" name="retour_mois" default=$mois }}
{{:button type="submit" name="suppr_occurrence" class="mini-x" shape="delete" title="Supprimer seulement ce jour" value=$bj.pid}}
{{*
<input type="hidden" name="perm_id" value="{{$bj.pid}}" />
<input type="hidden" name="date_exclue" value="{{$date_cellule}}" />
<input type="hidden" name="retour_an" value="{{$an}}" />
<input type="hidden" name="retour_mois" value="{{$mois}}" />
<button type="submit" name="suppr_occurrence" value="1" class="mini-x" title="Supprimer seulement ce jour">&#10005;</button>
*}}
</form>
</span>
{{/if}}
</div>
{{else}}
{{* background: hsl(var(--first-color), 50%, 90%);
background: linear-gradient(200deg, hsl(var(--first-color), 50%, 90%) 5%, hsl(var(--second-color), 30%, 90%) 30%);
*}}
<div class="evt-badge" style="background:hsl({{$bj.couleur}},100%,50%);">
<div class="badge-content" onclick="ouvrirDetailEvt(this);" data-titre="{{$bj.label}}" data-horaire="{{if $bj.debut}}{{$bj.debut}}{{if $bj.fin}}–{{$bj.fin}}{{/if}}{{/if}}" data-lieu="{{$bj.lieu}}" data-description="{{$bj.description}}" data-lien="{{$bj.lien}}" data-lien1-label="{{$bj.lien1_label}}" data-lien1-url="{{$bj.lien1_url}}" data-lien2-label="{{$bj.lien2_label}}" data-lien2-url="{{$bj.lien2_url}}" data-lien3-label="{{$bj.lien3_label}}" data-lien3-url="{{$bj.lien3_url}}">
{{if $bj.debut}}{{$bj.debut}}{{if $bj.fin}}–{{$bj.fin}}{{/if}} — {{/if}}{{$bj.label}}{{if $bj.lieu}}<br /><a class="lieu-lien" href="https://www.openstreetmap.org/search?query={{$bj.lieu|url_encode}}" target="_blank" rel="noopener" onclick="event.stopPropagation();">&#128205; {{$bj.lieu}}</a>{{/if}}
{{if $bj.description}}<div class="evt-desc-apercu">{{$bj.description}}</div>{{/if}}
</div>
{{if $est_admin}}
<span class="badge-actions">
<a class="badge-edit" href="index.html?edit_event={{$bj.id}}&amp;an={{$an}}&amp;mois={{$mois}}#form-event" title="Modifier" onclick="event.stopPropagation();">&#9998;</a>
<form method="post" action="" class="mini-form" onclick="event.stopPropagation();">
{{:input type="hidden" name="retour_an" default=$an }}
{{:input type="hidden" name="retour_mois" default=$mois }}
{{:button type="submit" name="suppr_event" class="mini-x" shape="delete" title="Supprimer" value=$bj.id}}
{{*
<input type="hidden" name="retour_an" value="{{$an}}" />
<input type="hidden" name="retour_mois" value="{{$mois}}" />
<button type="submit" name="suppr_event" value="{{$bj.id}}" class="mini-x" title="Supprimer">&#10005;</button>
*}}
</form>
</span>
{{/if}}
</div>
{{/if}}
{{/foreach}}
</td>
{{else}}
<td class="vide"></td>
{{/if}}
{{/if}}
{{if $vue == "mois" && "%d %% 7"|math:$n == 0 && $n != 42}}</tr><tr>{{/if}}
{{/foreach}}
</tr>
</tbody>
</table>
</div>
</div>
{{/if}}
+191
View File
@@ -0,0 +1,191 @@
{{* Gestion des Calendriers *}}
{{if $est_admin && $subconf=="manage_cal"}}
<div class="card">
<h2>Gérer les calendriers</h2>
<table class="permanences">
<thead><tr><th>Nom</th><th>Actions</th></tr></thead>
<tbody>
{{#foreach from=$calendriers_liste item="cd_gest"}}
<tr>
<td>
<span style="color:hsl({{$cd_gest.textecouleur}},100%,50%) ;background:hsl({{$cd_gest.couleur}},100%,50%);"> {{$cd_gest.nom}}</span>
{{if $cd_gest.par_defaut}} <small style="color:#999;">(par défaut)</small>{{/if}}</td>
<td>
{{:linkbutton href="index.html?nav=conf&conf=manage_cal&idcal=%s"|args:$cd_gest.id label="Modifier ce calendrier" class="mini" shape="edit"}}
<form method="post" action="" style="display:inline">
{{if !$cd_gest.par_defaut}}
{{:button type="submit" name="suppr_calendrier" label="Supprimer ce calendrier" class="mini" shape="delete" value="%s"|args:$cd_gest.id}}
{{/if}}
</form>
</td>
</tr>
{{/foreach}}
</tbody>
</table>
<p class="aide">Supprimer un calendrier ne supprime pas les événements/rendez-vous qui y étaient rattachés — ils basculent simplement dans "Agenda" par défaut.</p>
<form method="post" action="" class="ajout" style="margin-top:.8rem;">
<fieldset class="entree">
{{if $_GET.idcal && $est_admin}}
<h2>Modifier un calendrier</h2>
{{:assign var="_cnom" from="calendriers_liste.%s.nom"|args:$_GET.idcal}}
{{:assign var="_cdef" from="calendriers_liste.%s.par_defaut"|args:$_GET.idcal}}
{{:assign var="_ccou" from="calendriers_liste.%s.couleur"|args:$_GET.idcal}}
{{:assign var="_ctco" from="calendriers_liste.%s.textecouleur"|args:$_GET.idcal}}
{{:assign var="_ccat" from="calendriers_liste.%s.categorie"|args:$_GET.idcal}}
{{if $_cdef == true}}
{{:assign _checked="checked"}}
{{/if}}
<dl>{{:input type="text" name="nom_calendrier" label="Nom du calendrier" default=$_cnom required=true}}</dl>
<dl>{{:input type="hue" name="couleur" label="Couleur de l'arrière-plan" default=$_ccou}}</dl>
<dl>{{:input type="hue" name="couleur_texte" label="Couleur du texte" default=$_ctco}}</dl>
<dl>{{:input type="checkbox" name="pardefaut" label="Calendrier par défaut ?" checked="%s"|args:$_checked value=true}}</dl>
{{if $_ccat == "p"}} {{:assign _p="checked"}} {{elseif $_ccat == "m"}} {{:assign _m="checked"}} {{elseif $_ccat == "a"}} {{:assign _a="checked"}} {{else}} {{:assign _p="checked"}} {{/if}}
{{:assign var="options." id="p" texte="public" checked="%s"|args:$_p}}
{{:assign var="options." id="m" texte="membres" checked="%s"|args:$_m}}
{{:assign var="options." id="a" texte="admins" checked="%s"|args:$_a}}
<dl>
{{#foreach from=$options item="o"}}
{{:input type="radio" name="categorie" label="Catégorie" value=$o.id label=$o.texte checked=$o.checked}}
{{/foreach}}
{{*:input type="radio" name="categorie" label="Catégorie" checked="%s"|args:$_checked value=true*}}
</dl>
{{:button type="submit" name="mod_calendrier" label="Modifier" title="Modifier un calendrier" shape="plus" value="%d"|args:$_GET.idcal}}
{{else}}
<h2>Ajouter un calendrier</h2>
<dl>{{:input type="text" name="nom_calendrier" label="Nom du calendrier" help="ex. Réunions" required=true}}</dl>
<dl>{{:input type="hue" name="couleur" label="Couleur de l'arrière-plan" help="Couleur par defaut de l'arrière-plan des évènements créés dans ce calendrier." }}</dl>
<dl>{{:input type="hue" name="couleur_texte" label="Couleur du texte" default=$_ctco}}</dl>
<dl>{{:input type="checkbox" name="pardefaut" label="Calendrier par défaut ?" value=true}}</dl>
{{:assign var="options." id="p" texte="public" checked="checked"}}
{{:assign var="options." id="m" texte="membres"}}
{{:assign var="options." id="a" texte="admins"}}
<dl>
{{#foreach from=$options item="o"}}
{{:input type="radio" name="categorie" label="Catégorie" value=$o.id label=$o.texte checked=$o.checked}}
{{/foreach}}
</dl>
{{:button type="submit" name="add_calendrier" label="Ajouter" title="Ajouter un calendrier" shape="plus" value="1"}}
{{/if}}
</fieldset>
</form>
</div>
{{/if}}
{{* Gestion des évènements *}}
{{if $est_admin && $subconf=="manage_eve"}}
{{*:debug event=$event*}}
<form method="post" action="">
<fieldset class="entree">
<legend>{{if $edit_event}}Modifier l'événement{{else}}Ajouter un événement{{/if}}</legend>
<dl>
{{:input type="hidden" name="retour_an" default=$an}}
{{:input type="hidden" name="retour_mois" default=$mois}}
{{:input type="text" name="titre" label="Titre" default=$event.titre required=true}}
{{:input type="date" name="date" label="Date" default=$event.date required=true}}
{{:input type="time" name="debut" label="De" default=$event.debut}}
{{:input type="time" name="fin" label="À" default=$event.fin}}
{{:input type="text" name="lieu" label="Lieu" default=$event.lieu}}
{{if $edit_event}}
{{:input type="hue" name="couleur" label="Couleur" default=$event.couleur }}
{{/if}}
{{:assign var="ee_cal_eff" value=$event.calendrier}}
{{*if $ee_cal_eff == ""}}{{:assign var="ee_cal_eff" value="agenda"}}{{/if*}} {{* inutile *}}
{{#foreach from=$calendriers_liste item="cd_opt"}}
{{:assign var="calendriers_options.%s"|args:$cd_opt.id label=$cd_opt.nom}}
{{/foreach}}
{{*:debug cal=$calendriers_options*}}
{{:input type="select" name="calendrier" label="Calendrier" default=$event.calendrier options=$calendriers_options required=true}}
{{:input type="textarea" cols=40 rows=3 name="description" label="Description complète" default=$event.description required=false}}
{{#foreach count=3 key="i"}}
{{:assign var="i" value="1+%d"|math:$i}}
{{:assign _ell="event.lien%d_label"|args:$i _elu="event.lien%d_url"|args:$i}}
{{:assign var="ell" from=$_ell}}
{{:assign var="elu" from=$_elu}}
<div class="ajout">
{{:input type="text" name="lien%d_label"|args:$i label="Lien %d — libellé"|args:$i default=$ell placeholder="Ex. Inscription"}}
{{:input type="text" name="lien%d_url"|args:$i label="Lien %d — URL"|args:$i default=$elu placeholder="https://…"}}
{{/foreach}}
{{*
<div class="ajout">{{:input type="text" name="lien1_label" label="Lien 1 — libellé" default=$event.lien1_label placeholder="Ex. Affiche"}}{{:input type="text" name="lien1_url" label="Lien 1 — URL" default=$event.lien1_url placeholder="https://…"}}</div>
<div class="ajout">{{:input type="text" name="lien2_label" label="Lien 2 — libellé" default=$event.lien2_label placeholder="Ex. Programme"}}{{:input type="text" name="lien2_url" label="Lien 2 — URL" default=$event.lien2_url placeholder="https://…"}}</div>
<div class="ajout">{{:input type="text" name="lien3_label" label="Lien 3 — libellé" default=$event.lien3_label placeholder="Ex. Inscription"}}{{:input type="text" name="lien3_url" label="Lien 3 — URL" default=$event.lien3_url placeholder="https://…"}}</div>
*}}
</dl>
</fieldset>
<p class="submit">
{{if $edit_event}}
<a class="retour" href="?an={{$an}}&amp;mois={{$mois}}">Annuler</a>
{{:input type="hidden" name="event_id" default=$event.id}}
{{:button type="submit" name="save_event" label="Enregistrer les modifications" class="main"}}
{{else}}
{{:button type="submit" name="save_event" label="Ajouter l'événement" shape="plus" class="main"}}
{{/if}}
</p>
</form>
{{/if}}
{{* Gestion des occurences *}}
{{if $est_admin && $subconf=="manage_app"}}
<div class="card" id="form-perm">
<h2>{{if $edit_perm}}Modifier ce rendez-vous régulier{{else}}Ajouter un rendez-vous régulier{{/if}}</h2>
<form method="post" action="index.html">
<div class="ajout">
<div class="champ">
<label>Récurrence</label>
<select name="type_recurrence">
<option value="hebdomadaire" {{if $ep_type_recurrence != "mensuel" && $ep_type_recurrence != "quinzaine"}}selected="selected"{{/if}}>Chaque semaine</option>
<option value="quinzaine" {{if $ep_type_recurrence == "quinzaine"}}selected="selected"{{/if}}>Toutes les 2 semaines</option>
<option value="mensuel" {{if $ep_type_recurrence == "mensuel"}}selected="selected"{{/if}}>Un jour précis du mois</option>
</select>
</div>
<div class="champ">
<label>Jour</label>
<select name="jour">
<option value="1" {{if $ep_jour == 1}}selected="selected"{{/if}}>Lundi</option>
<option value="2" {{if $ep_jour == 2}}selected="selected"{{/if}}>Mardi</option>
<option value="3" {{if $ep_jour == 3}}selected="selected"{{/if}}>Mercredi</option>
<option value="4" {{if $ep_jour == 4}}selected="selected"{{/if}}>Jeudi</option>
<option value="5" {{if $ep_jour == 5}}selected="selected"{{/if}}>Vendredi</option>
<option value="6" {{if $ep_jour == 6}}selected="selected"{{/if}}>Samedi</option>
<option value="7" {{if $ep_jour == 7}}selected="selected"{{/if}}>Dimanche</option>
</select>
</div>
<div class="champ">
<label>Quel(le) — si "un jour précis du mois"</label>
<select name="semaine_du_mois">
<option value="1" {{if $ep_semaine_du_mois == 1}}selected="selected"{{/if}}>1er</option>
<option value="2" {{if $ep_semaine_du_mois == 2}}selected="selected"{{/if}}>2e</option>
<option value="3" {{if $ep_semaine_du_mois == 3}}selected="selected"{{/if}}>3e</option>
<option value="4" {{if $ep_semaine_du_mois == 4}}selected="selected"{{/if}}>4e</option>
<option value="-1" {{if $ep_semaine_du_mois == -1}}selected="selected"{{/if}}>Dernier</option>
</select>
</div>
<div class="champ"><label>De</label><input type="time" name="debut" value="{{$ep_debut}}" /></div>
<div class="champ"><label>À</label><input type="time" name="fin" value="{{$ep_fin}}" /></div>
<div class="champ" style="flex:2; min-width:14rem;"><label>Détail</label><input type="text" name="label" value="{{$ep_label}}" placeholder="ex. Ouvert aux adhérents" required="required" /></div>
<div class="champ" style="flex:1; min-width:10rem;"><label>Lieu (facultatif)</label><input type="text" name="lieu" value="{{$ep_lieu}}" placeholder="ex. Local associatif" /></div>
<div class="champ"><label>Depuis le (facultatif)</label><input type="date" name="date_debut" value="{{$ep_date_debut}}" /></div>
<div class="champ"><label>Jusqu'au (facultatif)</label><input type="date" name="date_fin" value="{{$ep_date_fin}}" /></div>
<div class="champ" style="flex:0 0 5rem;"><label>Couleur</label><input type="color" name="couleur" value="{{$ep_couleur|or:'#4c7a2e'}}" style="height:2.4rem; padding:.2rem;" /></div>
<div class="champ" style="flex:0 0 10rem;">
<label>Calendrier</label>
<select name="calendrier">
{{:assign var="ep_cal_eff" value=$ep_calendrier}}
{{if $ep_cal_eff == ""}}{{:assign var="ep_cal_eff" value="agenda"}}{{/if}}
{{#foreach from=$calendriers_liste item="cd_opt2"}}
<option value="{{$cd_opt2.id}}" {{if $cd_opt2.id == $ep_cal_eff}}selected="selected"{{/if}}>{{$cd_opt2.nom}}</option>
{{/foreach}}
</select>
</div>
</div>
<p><label>Description (facultatif)</label><textarea name="description" rows="2">{{$ep_description}}</textarea></p>
<p class="aide" style="color:#777; font-size:.85rem; margin:.4rem 0 0;">Laissez ces deux dates vides pour un rendez-vous permanent, sans limite dans le temps. Pour "Toutes les 2 semaines", renseignez "Depuis le" avec la date du premier rendez-vous : c'est elle qui sert de point de départ pour calculer une semaine sur deux.</p>
{{if $edit_perm}}
<button type="submit" name="rename_perm" value="{{$edit_perm}}">Enregistrer</button>
<a class="retour" href="index.html">Annuler</a>
{{else}}
<button type="submit" name="add_perm" value="1">Ajouter</button>
{{/if}}
</form>
</div>
{{/if}}
+50
View File
@@ -0,0 +1,50 @@
<div class="card">
<h2>{{if $vue == "liste"}}Calendrier en liste (3 prochains mois){{else}}Événements à venir{{/if}}</h2>
{{if $vue == "liste"}}
{{:assign var="rien_trouve" value=true}}
<ul class="liste-evt">
{{#foreach from=$liste_triee item="it"}}
{{:assign var="rien_trouve" value=false}}
<li>
<span class="date-evt">{{$it.date|date_long}}{{if $it.debut}} — {{$it.debut}}{{if $it.fin}} à {{$it.fin}}{{/if}}{{/if}}</span>
<span class="titre-evt">
<span class="tag-type" style="background:{{$it.couleur}};">{{$it.type}}</span>
{{$it.label}}
{{if $it.lien1_url}}<br /><a class="lien-evt" href="{{$it.lien1_url}}" target="_blank" rel="noopener">{{$it.lien1_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}
{{if $it.lien2_url}}<br /><a class="lien-evt" href="{{$it.lien2_url}}" target="_blank" rel="noopener">{{$it.lien2_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}
{{if $it.lien3_url}}<br /><a class="lien-evt" href="{{$it.lien3_url}}" target="_blank" rel="noopener">{{$it.lien3_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}
{{if !$it.lien1_url && !$it.lien2_url && !$it.lien3_url && $it.lien}}<br /><a class="lien-evt" href="{{$it.lien}}" target="_blank" rel="noopener">Voir l'affiche / plus d'infos &rarr;</a>{{/if}}
</span>
</li>
{{/foreach}}
</ul>
{{if $rien_trouve}}<p class="vide">Rien de prévu sur les 3 prochains mois.</p>{{/if}}
{{else}}
{{:assign var="event_trouve" value=false}}
<ul class="liste-evt">
{{#load where=$where_venir order="$$.date ASC"}}
{{:assign var="event_trouve" value=true}}
<li>
<span class="date-evt">{{$date|date_long}}{{if $debut}} — {{$debut}}{{if $fin}} à {{$fin}}{{/if}}{{/if}}</span>
<span class="titre-evt">{{$titre}}{{if $description}}<br /><small>{{$description}}</small>{{/if}}{{if $lien1_url}}<br /><a class="lien-evt" href="{{$lien1_url}}" target="_blank" rel="noopener">{{$lien1_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}{{if $lien2_url}}<br /><a class="lien-evt" href="{{$lien2_url}}" target="_blank" rel="noopener">{{$lien2_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}{{if $lien3_url}}<br /><a class="lien-evt" href="{{$lien3_url}}" target="_blank" rel="noopener">{{$lien3_label|or:"Voir l'affiche / plus d'infos"}} &rarr;</a>{{/if}}{{if !$lien1_url && !$lien2_url && !$lien3_url && $lien}}<br /><a class="lien-evt" href="{{$lien}}" target="_blank" rel="noopener">Voir l'affiche / plus d'infos &rarr;</a>{{/if}}</span>
{{if $lieu}}<span class="lieu-evt"><a href="https://www.openstreetmap.org/search?query={{$lieu|url_encode}}" target="_blank" rel="noopener">&#128205; {{$lieu}}</a></span>{{/if}}
{{if $est_admin}}
<span>
<a class="mini" href="index.html?edit_event={{$id}}&amp;an={{$an}}&amp;mois={{$mois}}#form-event" title="Modifier">&#9998;</a>
<form method="post" action="" style="display:inline">
{{:input type="hidden" name="retour_an" default=$an}}
{{:input type="hidden" name="retour_mois" default=$mois}}
{{:button type="submit" name="suppr_event" label="Supprimer" shape="delete" class="mini" default=$id required=true}}
{{*
<input type="hidden" name="retour_an" value="{{$an}}" />
<input type="hidden" name="retour_mois" value="{{$mois}}" />
<button type="submit" name="suppr_event" value="{{$id}}" class="mini" title="Supprimer">&#10005;</button>
*}}
</form>
</span>
{{/if}}
</li>
{{/load}}
</ul>
{{if !$event_trouve}}<p class="vide">Aucun événement à venir pour l'instant.</p>{{/if}}
{{/if}}
+72
View File
@@ -0,0 +1,72 @@
{{* Navigation *}}
{{#restrict section="web" level="write"}}
{{:assign _url="%sindex.html"|args:$module.url}}
{{else}}
{{if $is_logged==true}}
{{:assign _url="%sindex.html"|args:$module.url}}
{{else}}
{{:assign _url="%sagenda.html"|args:$module.url}}
{{/if}}
{{/restrict}}
<nav class="tabs">
{{if $current == 'agenda'}}
{{#restrict section="web" level="write"}}
<aside>
{{*:debug cf=$cal_filtre*}}
{{if $selected_calendar == -1}}
{{:button label="Tous les calendriers" shape="calendar" href="%s?vue=%s&an=%s&mois=%s&cal=-1"|args:$_url:$vue:$an:$mois disabled=true}}
{{else}}
{{:linkbutton label="Tous les calendriers" shape="calendar" href="%s?vue=%s&an=%s&mois=%s&cal=-1"|args:$_url:$vue:$an:$mois}}
{{/if}}
{{#foreach from=$calendriers_liste item="cd_tab"}}
{{if $selected_calendar == $cd_tab.id}}
{{:button label="%s"|args:$cd_tab.nom shape="calendar" href="%s?vue=%s&an=%s&mois=%s&cal=%s"|args:$_url:$vue:$an:$mois:$cd_tab.id disabled=true}}
{{else}}
{{:linkbutton label="%s"|args:$cd_tab.nom shape="calendar" href="%s?vue=%s&an=%s&mois=%s&cal=%s"|args:$_url:$vue:$an:$mois:$cd_tab.id}}
{{/if}}
{{/foreach}}
</aside>
{{/restrict}}
{{/if}}
{{* menu principal : exclus pour le site anonyme *}}
{{if $is_logged==true}}
<ul>
<li {{if $current == "agenda"}} class="current"{{/if}}><a href="{{$_url}}">Agenda</a></li>
{{#restrict section="web" level="write"}}
<li {{if $current == 'config'}} class="current"{{/if}}><a href="{{$_url}}?nav=conf">Configuration</a></li>
{{/restrict}}
</ul>
{{/if}}
{{* menu secondaire *}}
{{if $current == 'agenda'}}
{{:assign _liclass="current" _ulclass="sub"}}
{{if $is_logged==false}}
{{:assign _liclass="nav-mois" _ulclass="modal-liens"}}
{{/if}}
<ul class="{{$_ulclass}}">
<li {{if !$subcurrent || $subcurrent == 'mois'}} class="{{$_liclass}}"{{/if}}><a href="{{$_url}}?vue=mois&an={{$an}}&mois={{$mois}}">Mois</a></li>
<li {{if $subcurrent == 'semaine'}} class="{{$_liclass}}"{{/if}}><a href="{{$_url}}?vue=semaine&an={{$an}}&mois={{$mois}}">Semaine</a></li>
<li {{if $subcurrent == 'liste'}} class="{{$_liclass}}"{{/if}}><a href="{{$_url}}?vue=liste">Liste</a></li>
</ul>
{{/if}}
{{#restrict section="web" level="write"}}
{{if $current == 'config'}}
<ul class="sub">
<li {{if !$subcurrent || $subcurrent == 'manage_cal'}} class="current"{{/if}}><a href="{{$_url}}?nav={{$_GET.nav}}&conf=manage_cal">Calendriers</a></li>
<li {{if $subcurrent == 'manage_eve'}} class="current"{{/if}}><a href="{{$_url}}?nav={{$_GET.nav}}&conf=manage_eve">Évènements</a></li>
<li {{if $subcurrent == 'manage_app'}} class="current"{{/if}}><a href="{{$_url}}?nav={{$_GET.nav}}&conf=manage_app">RDV réguliers</a></li>
</ul>
{{/if}}
{{/restrict}}
</nav>
{{* Messages *}}
{{if $_GET.msg == "ajout" }}
<p class="block confirm">Ajout effectué</p>
{{elseif $_GET.msg == "modification" }}
<p class="block confirm">Modification effectuée</p>
{{elseif $_GET.msg == "suppression" }}
<p class="block confirm">Suppression effectuée</p>
{{elseif $_GET.msg == "supprmvtmat" }}
<p class="block confirm">Mouvement supprimé - Matériel supprimé</p>
{{/if}}
+87
View File
@@ -0,0 +1,87 @@
:root { --terra: #8c3a1e; --orange: #d9720f; --vert: #4c7a2e; }
* { box-sizing: border-box; }
/* body { margin: 0; padding: 1.5rem 1rem 3rem; font-family: "Trebuchet MS", Helvetica, sans-serif; background: #f4f6f2; color: #222; font-size: 1.08rem; }*/
.wrap { display: inline-block; max-width: 100rem; margin: 0 auto; }
a.retour { color: var(--terra); text-decoration: none; font-size: .95rem; }
a.retour:hover { text-decoration: underline; }
h1 { margin: .4rem 0 1.2rem; font-size: 1.7rem; color: var(--terra); }
.card { background: #fff; border: 1px solid #e2ddd9; border-radius: .6rem; padding: 1rem 1.2rem 1.2rem; margin-bottom: 1.2rem; box-shadow: 0 1px 4px rgba(0,0,0,.10); }
.card.card-perm { border-left: .35rem solid var(--vert); }
.card.card-perm h2 { color: var(--vert); }
.card.card-horaires table { width: 100%; border-collapse: collapse; }
.card.card-horaires table th, .card.card-horaires table td { padding: .35rem .5rem; text-align: left; border-bottom: 1px solid #eceae8; }
.card.card-horaires .activite { display: block; font-weight: bold; color: var(--terra); }
.card h2 { margin: 0 0 .8rem; font-size: 1.05rem; color: var(--terra); text-transform: uppercase; letter-spacing: .04em; }
.nav-mois { display: flex; align-items: center; justify-content: space-between; margin-bottom: .8rem; }
.nav-mois a { color: var(--terra); text-decoration: none; font-weight: bold; font-size: 1.3rem; padding: .1rem .6rem; }
.nav-mois a:hover { color: var(--orange); }
.nav-mois span { font-size: 1.15rem; font-weight: bold; text-transform: capitalize; color: var(--terra); }
.scroll-cal { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.calendrier { border-collapse: collapse; width: 100%; min-width: 46rem; table-layout: fixed; }
table.calendrier th { padding: .4rem; font-size: .9rem; color: #777; text-transform: uppercase; }
table.calendrier td { border: 1px solid #eceae8; vertical-align: top; height: 7.5rem; padding: .35rem; font-size: 1rem; }
table.calendrier td.vide { background: #fafafa; }
table.calendrier td .num { font-weight: bold; color: #555; font-size: 1.15rem; }
table.calendrier td.today { background: #fdf2e6; }
table.calendrier td.today .num { color: var(--orange); }
.evt-badge { color: #fff; border-radius: .3rem; padding: .15rem .4rem; margin-top: .25rem; font-size: .88rem; line-height: 1.3; display: flex; align-items: flex-start; justify-content: space-between; gap: .2rem; }
.evt-badge .badge-content { flex: 1; min-width: 0; cursor: pointer; white-space: normal; word-break: break-word; }
.evt-desc-apercu { margin-top: .15rem; font-size: .8rem; opacity: .85; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.perm-badge { color: #fff; border-radius: .3rem; padding: .15rem .4rem; margin-top: .25rem; font-size: .88rem; line-height: 1.3; opacity: .95; display: flex; align-items: flex-start; justify-content: space-between; gap: .2rem; }
.perm-badge .badge-content { flex: 1; min-width: 0; cursor: pointer; white-space: normal; word-break: break-word; }
.perm-badge span { white-space: normal; word-break: break-word; }
.perm-badge form.mini-form { display: inline; flex-shrink: 0; }
button.mini-x { background: none; border: none; color: #fff; opacity: .7; padding: 0; font-size: .8rem; line-height: 1; cursor: pointer; }
button.mini-x:hover { opacity: 1; }
.badge-actions { display: flex; align-items: center; gap: .35rem; flex-shrink: 0; }
a.badge-edit { color: #fff; opacity: .7; text-decoration: none; font-size: .85rem; line-height: 1.3; flex-shrink: 0; }
a.badge-edit:hover { opacity: 1; }
.modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 1000; align-items: center; justify-content: center; padding: 1rem; }
.modal-overlay.open { display: flex; }
.modal-box { background: #fff; border-radius: .6rem; padding: 1.2rem 1.4rem 1.4rem; max-width: 28rem; width: 100%; max-height: 82vh; overflow-y: auto; position: relative; box-shadow: 0 4px 24px rgba(0,0,0,.25); }
.modal-box h3 { margin: 0 1.6rem .3rem 0; color: var(--terra); }
.modal-meta { color: #777; font-size: .9rem; margin: .15rem 0; }
.modal-meta a { color: var(--terra); text-decoration: none; }
.modal-meta a:hover { text-decoration: underline; }
.modal-description { margin-top: .7rem; white-space: pre-wrap; }
.modal-liens { margin-top: .8rem; display: flex; flex-wrap: wrap; gap: .5rem; }
.modal-liens a { display: inline-block; background: var(--terra); color: #fff; text-decoration: none; padding: .45rem .9rem; border-radius: .4rem; font-size: .92rem; }
.modal-liens a:hover { background: var(--orange); }
.modal-close { position: absolute; top: .5rem; right: .6rem; background: none; border: none; font-size: 1.5rem; line-height: 1; color: #999; cursor: pointer; padding: .2rem .4rem; }
.modal-close:hover { color: var(--terra); }
ul.liste-evt { list-style: none; margin: 0; padding: 0; }
ul.liste-evt li { padding: .6rem 0; border-bottom: 1px solid #eceae8; display: flex; justify-content: space-between; gap: .8rem; align-items: baseline; flex-wrap: wrap; }
ul.liste-evt li:last-child { border-bottom: none; }
ul.liste-evt .date-evt { color: var(--terra); font-weight: bold; min-width: 9rem; }
ul.liste-evt .titre-evt { flex: 1; }
ul.liste-evt .lieu-evt { color: #777; font-size: .85rem; }
ul.liste-evt .lieu-evt a { color: inherit; text-decoration: none; }
ul.liste-evt .lieu-evt a:hover { text-decoration: underline; }
a.lieu-lien { color: inherit; text-decoration: none; }
a.lieu-lien:hover { text-decoration: underline; }
ul.liste-evt .lien-evt { color: var(--terra); font-size: .85rem; }
.tag-type { display: inline-block; color: #fff; font-size: .75rem; text-transform: uppercase; letter-spacing: .03em; padding: .1rem .4rem; border-radius: .3rem; margin-right: .4rem; vertical-align: middle; }
p.vide { color: #777; }
p.aide { color:#777; font-size:.85rem; margin:.6rem 0 0; }
table.permanences { border-collapse: collapse; width: 100%; }
.scroll-cal table.permanences { min-width: 42rem; }
table.permanences th, table.permanences td { padding: .5rem .4rem; text-align: left; border-bottom: 1px solid #eceae8; }
table.permanences th { color: #777; font-size: .8rem; text-transform: uppercase; }
input[type=text], input[type=date], input[type=time], input[type=url], textarea, select { font-family: inherit; font-size: 1rem; padding: .4rem .6rem; border: 1px solid #bbb; border-radius: .4rem; width: 100%; background: #fff; }
.ajout { display: flex; gap: .6rem; align-items: flex-end; flex-wrap: wrap; }
.ajout label { font-size: .85rem; color: #666; display: block; margin-bottom: .2rem; }
.ajout .champ { min-width: 9rem; }
button { font-family: inherit; font-size: .95rem; padding: .45rem .9rem; border: none; border-radius: .4rem; background: var(--terra); color: #fff; cursor: pointer; }
button:hover { background: var(--orange); }
button.mini { background: none; color: #999; padding: .1rem .3rem; font-size: .85rem; text-decoration: none; }
button.mini:hover { color: var(--terra); }
a.mini { color: #999; text-decoration: none; font-size: .85rem; padding: .1rem .3rem; }
a.mini:hover { color: var(--terra); }
.badge-admin { display: inline-block; background: var(--vert); color: #fff; font-size: .75rem; padding: .15rem .5rem; border-radius: 1rem; margin-left: .5rem; vertical-align: middle; }
nav.vue-tabs { display: flex; gap: .4rem; margin-bottom: 1.2rem; }
nav.vue-tabs a { color: var(--terra); text-decoration: none; font-weight: bold; padding: .4rem .9rem; border-radius: .4rem; background: #fff; border: 1px solid #e2ddd9; }
nav.vue-tabs a:hover { background: #fdf2e6; }
nav.vue-tabs a.current { background: var(--terra); color: #fff; border-color: var(--terra); }
nav.cal-tabs { margin-top: -.6rem; }
nav.cal-tabs a { font-weight: normal; font-size: .88rem; padding: .3rem .7rem; }
nav.cal-tabs a.current { background: var(--vert); border-color: var(--vert); }
+61
View File
@@ -0,0 +1,61 @@
{{* =========================================================================
FLUX ICALENDAR — module agenda
Placez ce fichier dans le module "agenda", nommé par exemple "flux.ics".
Les gens pourront s'abonner (lecture seule) avec l'URL publique de ce
fichier, ex: https://VOTRE-SITE/m/agenda/flux.ics
Limite connue : sans calcul de date avancé disponible dans ce langage,
l'heure de début de la récurrence (DTSTART) est calée sur la date de
début choisie (ou aujourd'hui si aucune n'est renseignée) même si son
jour de la semaine ne correspond pas exactement — ce n'est pas un
problème pour la plupart des calendriers, qui recalculent les
occurrences à partir de la règle BYDAY, mais à tester.
========================================================================= *}}
{{:assign var="aujourdhui_ics" value=$now|date:"Y-m-d"}}
{{* ---------- Codes des jours de la semaine pour BYDAY ---------- *}}
{{:assign var="jours_ical.1" value="MO"}}
{{:assign var="jours_ical.2" value="TU"}}
{{:assign var="jours_ical.3" value="WE"}}
{{:assign var="jours_ical.4" value="TH"}}
{{:assign var="jours_ical.5" value="FR"}}
{{:assign var="jours_ical.6" value="SA"}}
{{:assign var="jours_ical.7" value="SU"}}
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//{{$config.org_name}}//Agenda//FR
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:{{$config.org_name}} — Agenda
{{#load where="$$.type = 'event'" order="$$.date ASC"}}
BEGIN:VEVENT
UID:evt-{{$id}}@{{$config.org_name|strval|replace:" ":"-"}}
DTSTAMP:{{$aujourdhui_ics|date:"Ymd"}}T000000Z
DTSTART:{{$date|date:"Ymd"}}T{{$debut|strval|replace:":":""}}00
{{if $fin}}DTEND:{{$date|date:"Ymd"}}T{{$fin|strval|replace:":":""}}00
{{/if}}SUMMARY:{{$titre|strval|replace:"\\":"\\\\"|replace:",":"\,"|replace:";":"\;"}}
{{if $lieu}}LOCATION:{{$lieu|strval|replace:"\\":"\\\\"|replace:",":"\,"|replace:";":"\;"}}
{{/if}}{{if $description}}DESCRIPTION:{{$description|strval|replace:"\\":"\\\\"|replace:",":"\,"|replace:";":"\;"|replace:"
":" "}}
{{/if}}END:VEVENT
{{/load}}
{{#load where="$$.type = 'permanence'" order="$$.jour ASC"}}
{{:assign var="jc" from="jours_ical.%s"|args:$jour}}
{{:assign var="dtstart_date" value=$date_debut}}
{{if !$dtstart_date}}{{:assign var="dtstart_date" value=$aujourdhui_ics}}{{/if}}
BEGIN:VEVENT
UID:perm-{{$id}}@{{$config.org_name|strval|replace:" ":"-"}}
DTSTAMP:{{$aujourdhui_ics|date:"Ymd"}}T000000Z
DTSTART:{{$dtstart_date|date:"Ymd"}}T{{$debut|strval|replace:":":""}}00
{{if $fin}}DTEND:{{$dtstart_date|date:"Ymd"}}T{{$fin|strval|replace:":":""}}00
{{/if}}{{if $type_recurrence == "mensuel"}}RRULE:FREQ=MONTHLY;BYDAY={{$semaine_du_mois}}{{$jc}}{{if $date_fin}};UNTIL={{$date_fin|date:"Ymd"}}T235959Z{{/if}}
{{else}}RRULE:FREQ=WEEKLY;BYDAY={{$jc}}{{if $date_fin}};UNTIL={{$date_fin|date:"Ymd"}}T235959Z{{/if}}
{{/if}}{{#foreach from=$exceptions item="ex_ics"}}EXDATE:{{$ex_ics|date:"Ymd"}}T{{$debut|strval|replace:":":""}}00
{{/foreach}}SUMMARY:{{$label|strval|replace:"\\":"\\\\"|replace:",":"\,"|replace:";":"\;"}}
{{if $lieu}}LOCATION:{{$lieu|strval|replace:"\\":"\\\\"|replace:",":"\,"|replace:";":"\;"}}
{{/if}}END:VEVENT
{{/load}}
END:VCALENDAR
+505
View File
@@ -0,0 +1,505 @@
{{* =========================================================================
MODULE AGENDA
ADMINISTRATION : accès admin géré par les permissions Paheko réelles
(membre connecté avec droit d'écriture sur la section "web"), via
{{#restrict}} ci-dessous. Plus de code partagé dans l'URL.
========================================================================= *}}
{{#restrict section="web" level="write"}}
{{:assign var="est_admin" value=true}}
{{else}}
{{if $is_logged==true}}
{{:assign _url="%sindex.html"|args:$module.url}}
{{else}}
{{:assign _url="%sagenda.html"|args:$module.url}}
{{/if}}
{{:assign var="est_admin" value=false}}
{{/restrict}}
{{if $est_admin==true}}
{{:admin_header title="Agenda" custom_css="/m/agenda/agenda.css" layout="" current="module_agenda"}}
{{* {{else}} TODO membre logué
<link rel='stylesheet' id='agenda-css' href='agenda.css' media='all'/>*}}
{{/if}}
{{* ---------- Temp correction ---------- *}}
{{*:delete where="$$.type = :type AND id > 9" :type="event"*}}
{{*:save key="c489ba90-16d0-42cb-b5b8-8daa2f7e0d06" date="28/10/2026"|parse_date*}}
{{* ---------- Gestion des événements ---------- *}}
{{if $_POST.save_event || $_POST.suppr_event }}
{{:include file="manage/_event.html"}}
{{/if}}
{{* ---------- Gestion des permanences ---------- *}}
{{if $_POST.add_perm || $_POST.rename_perm || $_POST.suppr_perm}}
{{:include file="manage/_perm.html"}}
{{/if}}
{{* ---------- Gestion des occurrences ---------- *}}
{{if $_POST.suppr_occurrence }}
{{:include file="manage/_occurence.html"}}
{{/if}}
{{* ---------- Gestion des calendriers ---------- *}}
{{if $_POST.add_calendrier || $_POST.suppr_calendrier || $_POST.mod_calendrier}}
{{:include file="manage/_calendrier.html"}}
{{/if}}
{{* ---------- Mois affiché (par défaut : le mois en cours) ---------- *}}
{{:assign var="an" value=$_GET.an|intval}}
{{:assign var="mois" value=$_GET.mois|intval}}
{{if $an < 1}}{{:assign var="an" value=$now|date:"Y"}}{{/if}}
{{if $mois < 1 || $mois > 12}}{{:assign var="mois" value=$now|date:"n"}}{{/if}}
{{:assign var="premier_du_mois" value="%04d-%02d-01"|args:$an:$mois}}
{{:assign var="nb_jours" value=$premier_du_mois|date:"t"}}
{{:assign var="dow_premier" value=$premier_du_mois|date:"N"}}
{{:assign var="decalage" value="%d-1"|math:$dow_premier}}
{{:assign var="nom_mois" value=$premier_du_mois|date:"F Y"}}
{{:assign var="aujourdhui" value=$now|date:"Y-m-d"}}
{{* ---------- Mois précédent / suivant ---------- *}}
{{if $mois == 1}}
{{:assign var="mois_prec" value=12}}
{{:assign var="an_prec" value="%d-1"|math:$an}}
{{else}}
{{:assign var="mois_prec" value="%d-1"|math:$mois}}
{{:assign var="an_prec" value=$an}}
{{/if}}
{{if $mois == 12}}
{{:assign var="mois_suiv" value=1}}
{{:assign var="an_suiv" value="%d+1"|math:$an}}
{{else}}
{{:assign var="mois_suiv" value="%d+1"|math:$mois}}
{{:assign var="an_suiv" value=$an}}
{{/if}}
{{* ---------- Vue choisie : mois (défaut), semaine ou liste ---------- *}}
{{if $_GET.nav != "conf"}}
{{:assign var="vue" value=$_GET.vue|strval|trim}}
{{if $vue != "semaine" && $vue != "liste"}}{{:assign var="vue" value="mois"}}{{/if}}
{{/if}}
{{* ---------- Liste des calendriers disponibles ---------- *}}
{{#load module="agenda" where="$$.type = 'calendrier'" order="$$.nom ASC"}}
{{:assign var="calendriers_liste.%s.id"|args:$id value=$id}}
{{:assign var="calendriers_liste.%s.nom"|args:$id value=$nom}}
{{:assign var="calendriers_liste.%s.par_defaut"|args:$id value=$par_defaut}}
{{:assign var="calendriers_liste.%s.couleur"|args:$id value=$couleur}}
{{:assign var="calendriers_liste.%s.textecouleur"|args:$id value=$textecouleur}}
{{:assign var="calendriers_liste.%s.categorie"|args:$id value=$categorie}}
{{else}}
{{* Pas encore de calendrier créé : vérifier que nous ne sommes pas sur le site web *}}
{{if $module.name == "agenda"}}
{{:save type="calendrier" nom="Agenda" par_defaut=true couleur=180 textecouleur="225" categorie="p"}}
{{/if}}
{{/load}}
{{* ---------- Liste des calendriers publics (Web) ---------- *}}
{{if $module.name == "web"}}
{{:assign filtre_cal_sql="1"}}
{{#foreach from=$calendriers_liste item="value"}}
{{if $value.categorie == "p"}}
{{:assign var="calendriers_publics." id=$id value=$nom}}
{{:assign filtre_cal_sql=" AND $$.calendrier = '%d' AND %s"|args:$id:$filtre_cal_sql}}
{{/if}}
{{/foreach}}
{{:assign selected_calendar=-1 selected_calendar_name="Public" selected_calendar_couleur=180}}
{{*:debug filtre_cal_sql=$filtre_cal_sql*}}
{{/if}}
{{* ---------- Filtre calendrier (Utilisateurs logués) ---------- *}}
{{if $is_logged==true}}
{{:assign saved_filters=$module.config.filters}}
{{:assign var="user_filters" from="saved_filters.%s"|args:$logged_user.id}}
{{if $_GET.cal == null}}
{{:assign selected_calendar=$user_filters.cal_key }}
{{:assign var="selected_calendar_name" from="calendriers_liste.%s.nom"|args:$selected_calendar}}
{{:assign var="selected_calendar_couleur" from="calendriers_liste.%s.couleur"|args:$selected_calendar}}
{{if $selected_calendar == -1}}
{{:assign filtre_cal_sql=""}}
{{else}}
{{:assign filtre_cal_sql=" AND $$.calendrier = '%s'"|args:$selected_calendar}}
{{/if}}
{{else}}
{{*
-1 = Tous
n = Id du calendrier dans la base
*}}
{{if $_GET.cal == -1}}
{{:assign selected_calendar=-1 selected_calendar_name="Tous" selected_calendar_couleur=180}}
{{:assign filtre_cal_sql=""}}
{{else}}
{{:assign selected_calendar=$_GET.cal}}
{{:assign var="selected_calendar_name" from="calendriers_liste.%s.nom"|args:$selected_calendar}}
{{:assign var="selected_calendar_couleur" from="calendriers_liste.%s.couleur"|args:$selected_calendar}}
{{:assign filtre_cal_sql=" AND $$.calendrier = '%s'"|args:$selected_calendar}}
{{/if}}
{{:assign var="user_filters.cal_key" value=$selected_calendar}}
{{:assign var="saved_filters.%s"|args:$logged_user.id value=$user_filters}}
{{:save key="config" filters=$saved_filters}}
{{/if}}
{{else}}
{{:assign selected_calendar=$_GET.cal}}
{{/if}}
{{*:debug _GET=$_GET scal=$selected_calendar fsql=$filtre_cal_sql user_cal=$user_filters.cal_key*}}
{{* ---------- Nombre de rangées du mois affiché, et du mois précédent (pour la navigation par semaine) ---------- *}}
{{:assign var="total_rows" value="ceil((%d+%d)/7)"|math:$nb_jours:$decalage}}
{{:assign var="premier_du_mois_prec" value="%04d-%02d-01"|args:$an_prec:$mois_prec}}
{{:assign var="nb_jours_prec" value=$premier_du_mois_prec|date:"t"}}
{{:assign var="dow_premier_prec" value=$premier_du_mois_prec|date:"N"}}
{{:assign var="decalage_prec" value="%d-1"|math:$dow_premier_prec}}
{{:assign var="total_rows_prec" value="ceil((%d+%d)/7)"|math:$nb_jours_prec:$decalage_prec}}
{{* ---------- Rangée sélectionnée pour la vue semaine (par défaut : celle contenant aujourd'hui) ---------- *}}
{{:assign var="semaine_sel" value=$_GET.semaine_sel|intval}}
{{if $semaine_sel < 1}}
{{:assign var="jour_today_num" value=$aujourdhui|date:"j"}}
{{if $an == $now|date:"Y" && $mois == $now|date:"n"}}
{{:assign var="semaine_sel" value="ceil((%d+%d)/7)"|math:$jour_today_num:$decalage}}
{{else}}
{{:assign var="semaine_sel" value=1}}
{{/if}}
{{/if}}
{{if $semaine_sel > $total_rows}}{{:assign var="semaine_sel" value=$total_rows}}{{/if}}
{{* ---------- Purge automatique des événements passés et rendez-vous réguliers expirés ---------- *}}
{{* FB : Ne Fonctionne pas : erreur "Database is locked" / perso ca m'arrrange de conserver les anciens RDV pour avoir une trace ;-)SS *}}
{{:assign var="purge_faite" value=false}}
{{:assign var="where_purge_evt" value="$$.type = 'event' AND $$.date < '%s'"|args:$aujourdhui}}
{{#load module="agenda" where=$where_purge_evt}}
{{*:delete id=$id*}}
{{*:debug id=$id*}}
{{:assign var="purge_faite" value=true}}
{{/load}}
{{:assign var="where_purge_perm" value="$$.type = 'permanence' AND $$.date_fin != '' AND $$.date_fin < '%s'"|args:$aujourdhui}}
{{#load module="agenda" where=$where_purge_perm}}
{{*:delete id=$id*}}
{{*:debug id=$id*}}
{{:assign var="purge_faite" value=true}}
{{/load}}
{{if $purge_faite}}
{{* FB : provoque une redirection en boucle et un timeout *}}
{{*:redirect url="index.html?vue=%s&an=%s&mois=%s&cal=%s"|args:$vue:$an:$mois:$cal_filtre*}}
{{/if}}
{{* ---------- Chargement des événements du mois affiché (pour la grille) ---------- *}}
{{:assign var="date_fin_mois" value="%04d-%02d-%02d"|args:$an:$mois:$nb_jours}}
{{:assign var="where_mois" value="$$.type = 'event' AND $$.date >= '%s' AND $$.date <= '%s'%s"|args:$premier_du_mois:$date_fin_mois:$filtre_cal_sql}}
{{#load module="agenda" where=$where_mois order="$$.date ASC" }}
{{:assign var="events_par_jour.%s.%s.titre"|args:$date:$id value=$titre}}
{{:assign var="events_par_jour.%s.%s.id"|args:$date:$id value=$id}}
{{:assign var="events_par_jour.%s.%s.debut"|args:$date:$id value=$debut}}
{{:assign var="events_par_jour.%s.%s.fin"|args:$date:$id value=$fin}}
{{:assign var="events_par_jour.%s.%s.couleur"|args:$date:$id value=$couleur}}
{{:assign var="events_par_jour.%s.%s.lieu"|args:$date:$id value=$lieu}}
{{:assign var="events_par_jour.%s.%s.description"|args:$date:$id value=$description}}
{{:assign var="events_par_jour.%s.%s.lien"|args:$date:$id value=$lien}}
{{:assign var="events_par_jour.%s.%s.lien1_label"|args:$date:$id value=$lien1_label}}
{{:assign var="events_par_jour.%s.%s.lien1_url"|args:$date:$id value=$lien1_url}}
{{:assign var="events_par_jour.%s.%s.lien2_label"|args:$date:$id value=$lien2_label}}
{{:assign var="events_par_jour.%s.%s.lien2_url"|args:$date:$id value=$lien2_url}}
{{:assign var="events_par_jour.%s.%s.lien3_label"|args:$date:$id value=$lien3_label}}
{{:assign var="events_par_jour.%s.%s.lien3_url"|args:$date:$id value=$lien3_url}}
{{/load}}
{{* ---------- Préchargement des permanences (pour la grille, avec vérification date début/fin) ---------- *}}
{{:assign var="where_perms" value="$$.type = 'permanence'%s"|args:$filtre_cal_sql}}
{{#load module="agenda" where=$where_perms order="$$.jour ASC, $$.debut ASC"}}
{{:assign var="perms_data.%s.id"|args:$id value=$id}}
{{:assign var="perms_data.%s.jour"|args:$id value=$jour}}
{{:assign var="perms_data.%s.label"|args:$id value=$label}}
{{:assign var="perms_data.%s.lieu"|args:$id value=$lieu}}
{{:assign var="perms_data.%s.description"|args:$id value=$description}}
{{:assign var="perms_data.%s.debut"|args:$id value=$debut}}
{{:assign var="perms_data.%s.fin"|args:$id value=$fin}}
{{:assign var="perms_data.%s.date_debut"|args:$id value=$date_debut}}
{{:assign var="perms_data.%s.date_fin"|args:$id value=$date_fin}}
{{:assign var="perms_data.%s.type_recurrence"|args:$id value=$type_recurrence}}
{{:assign var="perms_data.%s.semaine_du_mois"|args:$id value=$semaine_du_mois}}
{{:assign var="perms_data.%s.exceptions"|args:$id value=$exceptions}}
{{:assign var="perms_data.%s.couleur"|args:$id value=$couleur}}
{{/load}}
{{* ---------- Chargement des événements à venir (pour la liste) ---------- *}}
{{:assign var="where_venir" value="$$.type = 'event' AND $$.date >= '%s'%s"|args:$aujourdhui:$filtre_cal_sql}}
{{* ---------- Vue Liste uniquement : occurrences des rendez-vous réguliers sur les 3 prochains mois, fusionnées avec les événements ---------- *}}
{{if $vue == "liste"}}
{{#load module="agenda" where=$where_venir order="$$.date ASC"}}
{{:assign var="cle_liste" value="%s_%s_evt%s"|args:$date:$debut:$id}}
{{:assign var="liste_fusionnee.%s.date"|args:$cle_liste value=$date}}
{{:assign var="liste_fusionnee.%s.debut"|args:$cle_liste value=$debut}}
{{:assign var="liste_fusionnee.%s.fin"|args:$cle_liste value=$fin}}
{{:assign var="liste_fusionnee.%s.label"|args:$cle_liste value=$titre}}
{{:assign var="liste_fusionnee.%s.couleur"|args:$cle_liste value=$couleur|or:"#8c3a1e"}}
{{:assign var="liste_fusionnee.%s.type"|args:$cle_liste value="Événement"}}
{{:assign var="liste_fusionnee.%s.lien"|args:$cle_liste value=$lien}}
{{:assign var="liste_fusionnee.%s.lien1_label"|args:$cle_liste value=$lien1_label}}
{{:assign var="liste_fusionnee.%s.lien1_url"|args:$cle_liste value=$lien1_url}}
{{:assign var="liste_fusionnee.%s.lien2_label"|args:$cle_liste value=$lien2_label}}
{{:assign var="liste_fusionnee.%s.lien2_url"|args:$cle_liste value=$lien2_url}}
{{:assign var="liste_fusionnee.%s.lien3_label"|args:$cle_liste value=$lien3_label}}
{{:assign var="liste_fusionnee.%s.lien3_url"|args:$cle_liste value=$lien3_url}}
{{/load}}
{{* -- Mois 1 : le mois en cours -- *}}
{{:assign var="an_m0" value=$now|date:"Y"}}
{{:assign var="mois_m0" value=$now|date:"n"}}
{{* -- Mois 2 : le mois suivant -- *}}
{{if $mois_m0 == 12}}{{:assign var="mois_m1" value=1}}{{:assign var="an_m1" value="%d+1"|math:$an_m0}}
{{else}}{{:assign var="mois_m1" value="%d+1"|math:$mois_m0}}{{:assign var="an_m1" value=$an_m0}}{{/if}}
{{* -- Mois 3 : encore le mois suivant -- *}}
{{if $mois_m1 == 12}}{{:assign var="mois_m2" value=1}}{{:assign var="an_m2" value="%d+1"|math:$an_m1}}
{{else}}{{:assign var="mois_m2" value="%d+1"|math:$mois_m1}}{{:assign var="an_m2" value=$an_m1}}{{/if}}
{{:assign var="jours_du_mois." value=1}}{{:assign var="jours_du_mois." value=2}}{{:assign var="jours_du_mois." value=3}}{{:assign var="jours_du_mois." value=4}}{{:assign var="jours_du_mois." value=5}}{{:assign var="jours_du_mois." value=6}}{{:assign var="jours_du_mois." value=7}}{{:assign var="jours_du_mois." value=8}}{{:assign var="jours_du_mois." value=9}}{{:assign var="jours_du_mois." value=10}}
{{:assign var="jours_du_mois." value=11}}{{:assign var="jours_du_mois." value=12}}{{:assign var="jours_du_mois." value=13}}{{:assign var="jours_du_mois." value=14}}{{:assign var="jours_du_mois." value=15}}{{:assign var="jours_du_mois." value=16}}{{:assign var="jours_du_mois." value=17}}{{:assign var="jours_du_mois." value=18}}{{:assign var="jours_du_mois." value=19}}{{:assign var="jours_du_mois." value=20}}
{{:assign var="jours_du_mois." value=21}}{{:assign var="jours_du_mois." value=22}}{{:assign var="jours_du_mois." value=23}}{{:assign var="jours_du_mois." value=24}}{{:assign var="jours_du_mois." value=25}}{{:assign var="jours_du_mois." value=26}}{{:assign var="jours_du_mois." value=27}}{{:assign var="jours_du_mois." value=28}}{{:assign var="jours_du_mois." value=29}}{{:assign var="jours_du_mois." value=30}}
{{:assign var="jours_du_mois." value=31}}
{{:assign var="mois_traite_an.0" value=$an_m0}}{{:assign var="mois_traite_mois.0" value=$mois_m0}}
{{:assign var="mois_traite_an.1" value=$an_m1}}{{:assign var="mois_traite_mois.1" value=$mois_m1}}
{{:assign var="mois_traite_an.2" value=$an_m2}}{{:assign var="mois_traite_mois.2" value=$mois_m2}}
{{:assign var="idx_mois." value=0}}
{{:assign var="idx_mois." value=1}}
{{:assign var="idx_mois." value=2}}
{{#foreach from=$idx_mois item="idx_m"}}
{{:assign var="an_l2" from="mois_traite_an.%s"|args:$idx_m}}
{{:assign var="mois_l2" from="mois_traite_mois.%s"|args:$idx_m}}
{{:assign var="premier_l2" value="%04d-%02d-01"|args:$an_l2:$mois_l2}}
{{:assign var="nb_jours_l2" value=$premier_l2|date:"t"}}
{{#foreach from=$jours_du_mois item="jn"}}
{{if $jn <= $nb_jours_l2}}
{{:assign var="date_l2" value="%04d-%02d-%02d"|args:$an_l2:$mois_l2:$jn}}
{{if $date_l2 >= $aujourdhui}}
{{:assign var="dow_l2" value=$date_l2|date:"N"}}
{{:assign var="occ_l2" value="floor((%d-1)/7)+1"|math:$jn}}
{{:assign var="derniere_l2" value=false}}
{{if "%d+7"|math:$jn > $nb_jours_l2}}{{:assign var="derniere_l2" value=true}}{{/if}}
{{#foreach from=$perms_data item="pd"}}
{{if $pd.jour == $dow_l2}}
{{if $pd.date_debut == "" || $date_l2 >= $pd.date_debut}}
{{if $pd.date_fin == "" || $date_l2 <= $pd.date_fin}}
{{:assign var="excl_l2" value=false}}
{{#foreach from=$pd.exceptions item="ex2"}}
{{if $ex2 == $date_l2}}{{:assign var="excl_l2" value=true}}{{/if}}
{{/foreach}}
{{if !$excl_l2}}
{{:assign var="ok_l2" value=false}}
{{if $pd.type_recurrence == "mensuel"}}
{{if $pd.semaine_du_mois == -1 && $derniere_l2}}{{:assign var="ok_l2" value=true}}{{/if}}
{{if $pd.semaine_du_mois == $occ_l2}}{{:assign var="ok_l2" value=true}}{{/if}}
{{elseif $pd.type_recurrence == "quinzaine"}}
{{if $pd.date_debut != ""}}
{{:assign var="ref_sem_q2" value=$pd.date_debut|date:"W"|intval}}
{{:assign var="cell_sem_q2" value=$date_l2|date:"W"|intval}}
{{:assign var="diff_sem_q2" value="(%d-%d) %% 2"|math:$cell_sem_q2:$ref_sem_q2}}
{{if $diff_sem_q2 == 0}}{{:assign var="ok_l2" value=true}}{{/if}}
{{/if}}
{{else}}
{{:assign var="ok_l2" value=true}}
{{/if}}
{{if $ok_l2}}
{{:assign var="cle_liste2" value="%s_%s_perm%s"|args:$date_l2:$pd.debut:$pd.id}}
{{:assign var="liste_fusionnee.%s.date"|args:$cle_liste2 value=$date_l2}}
{{:assign var="liste_fusionnee.%s.debut"|args:$cle_liste2 value=$pd.debut}}
{{:assign var="liste_fusionnee.%s.fin"|args:$cle_liste2 value=$pd.fin}}
{{:assign var="liste_fusionnee.%s.label"|args:$cle_liste2 value=$pd.label}}
{{:assign var="liste_fusionnee.%s.couleur"|args:$cle_liste2 value=$pd.couleur|or:"#4c7a2e"}}
{{:assign var="liste_fusionnee.%s.type"|args:$cle_liste2 value="Rendez-vous régulier"}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/foreach}}
{{/if}}
{{/if}}
{{/foreach}}
{{/foreach}}
{{:assign var="liste_triee" value=$liste_fusionnee|ksort|values}}
{{/if}}
{{* ---------- Noms des jours ---------- *}}
{{:assign var="noms_jours." value=""}}
{{:assign var="noms_jours." value="Lundi"}}
{{:assign var="noms_jours." value="Mardi"}}
{{:assign var="noms_jours." value="Mercredi"}}
{{:assign var="noms_jours." value="Jeudi"}}
{{:assign var="noms_jours." value="Vendredi"}}
{{:assign var="noms_jours." value="Samedi"}}
{{:assign var="noms_jours." value="Dimanche"}}
{{* ---------- Événement / permanence en cours de modification ---------- *}}
{{:assign var="edit_event" value=$_GET.edit_event|intval}}
{{if $edit_event}}
{{#load id=$edit_event assign="event"}}
{{:assign var="ee_titre" value=$titre}}
{{:assign var="ee_date" value=$date}}
{{:assign var="ee_debut" value=$debut}}
{{:assign var="ee_fin" value=$fin}}
{{:assign var="ee_lieu" value=$lieu}}
{{:assign var="ee_description" value=$description}}
{{:assign var="ee_lien1_label" value=$lien1_label}}
{{:assign var="ee_lien1_url" value=$lien1_url}}
{{:assign var="ee_lien2_label" value=$lien2_label}}
{{:assign var="ee_lien2_url" value=$lien2_url}}
{{:assign var="ee_lien3_label" value=$lien3_label}}
{{:assign var="ee_lien3_url" value=$lien3_url}}
{{if $ee_lien1_url == "" && $ee_lien2_url == "" && $ee_lien3_url == "" && $lien != ""}}
{{:assign var="ee_lien1_url" value=$lien}}
{{/if}}
{{:assign var="ee_couleur" value=$couleur}}
{{:assign var="ee_calendrier" value=$calendrier}}
{{/load}}
{{/if}}
{{:assign var="edit_perm" value=$_GET.edit_perm|intval}}
{{if $edit_perm}}
{{#load id=$edit_perm assign="perm"}}
{{:assign var="ep_jour" value=$jour}}
{{:assign var="ep_debut" value=$debut}}
{{:assign var="ep_fin" value=$fin}}
{{:assign var="ep_label" value=$label}}
{{:assign var="ep_lieu" value=$lieu}}
{{:assign var="ep_description" value=$description}}
{{:assign var="ep_date_debut" value=$date_debut}}
{{:assign var="ep_date_fin" value=$date_fin}}
{{:assign var="ep_type_recurrence" value=$type_recurrence}}
{{:assign var="ep_semaine_du_mois" value=$semaine_du_mois}}
{{:assign var="ep_couleur" value=$couleur}}
{{:assign var="ep_calendrier" value=$calendrier}}
{{/load}}
{{/if}}
{{*
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Agenda — {{$config.org_name}}</title>
</style>
</head>
<body>*}}
{{* Si edition ou suppression d'évenements ou RDV *}}
{{if $est_admin==true}}
{{if $_GET.edit_event > 0}}
{{:assign _nav="conf"}}
{{:assign _conf="manage_eve"}}
{{elseif $_GET.edit_perm > 0}}
{{:assign _nav="conf"}}
{{:assign _conf="manage_app"}}
{{else}}
{{:assign _nav=$_GET.nav}}
{{:assign _conf=$_GET.conf}}
{{/if}}
{{/if}}
{{* Navigation *}}
{{if $_nav == "conf"}}
{{if !$_conf}}
{{:include file="_nav.html" current="config" subcurrent="manage_cal"}}
{{:assign _conf="manage_cal"}}
{{else}}
{{:include file="_nav.html" current="config" subcurrent="%s"|args:$_conf}}
{{:assign _conf=$_conf}}
{{/if}}
{{:include file="_config.html" subconf=$_conf}}
{{else}}
{{:include file="_nav.html" current="agenda" subcurrent="%s"|args:$vue vue=$vue an=$an mois=$mois cal=$cal_filtre}}
{{/if}}
<div class="wrap">
{{if $vue == "mois" || $vue == "semaine"}}
{{:include file="_calendar.html" vue=$vue}}
{{elseif $vue == "liste"}}
{{:include file="_appointments_list.html" vue=$vue}}
{{:include file="_events_list.html" vue=$vue}}
{{/if}}
</div>
<div class="modal-overlay" id="modalDetailEvt" onclick="if(event.target===this){fermerDetailEvt();}">
<div class="modal-box" role="dialog" aria-modal="true" aria-labelledby="modalDetailTitre">
<button type="button" class="modal-close" onclick="fermerDetailEvt();" aria-label="Fermer">&times;</button>
<h3 id="modalDetailTitre"></h3>
<p class="modal-meta" id="modalDetailHoraire"></p>
<p class="modal-meta" id="modalDetailLieu"></p>
<p class="modal-description" id="modalDetailDescription"></p>
<div class="modal-liens" id="modalDetailLiens"></div>
</div>
</div>
<script type="text/javascript">
function echapperHtml(str) {
return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}
function lienifier(str) {
return echapperHtml(str).replace(/(https?:\/\/[^\s<]+)/g, function(url) {
var suffixe = '';
var m = url.match(/[.,;:!?)]+$/);
if (m) { suffixe = m[0]; url = url.slice(0, -suffixe.length); }
return '<a href="' + url + '" target="_blank" rel="noopener">' + url + '</a>' + suffixe;
});
}
function ouvrirDetailEvt(el) {
document.getElementById('modalDetailTitre').textContent = el.getAttribute('data-titre') || '';
var horaire = el.getAttribute('data-horaire') || '';
var elH = document.getElementById('modalDetailHoraire');
elH.textContent = horaire;
elH.style.display = horaire ? '' : 'none';
var lieu = el.getAttribute('data-lieu') || '';
var elL = document.getElementById('modalDetailLieu');
if (lieu) {
elL.innerHTML = '<a href="https://www.openstreetmap.org/search?query=' + encodeURIComponent(lieu) + '" target="_blank" rel="noopener">📍 ' + echapperHtml(lieu) + '</a>';
elL.style.display = '';
} else {
elL.style.display = 'none';
}
var desc = el.getAttribute('data-description') || '';
var elD = document.getElementById('modalDetailDescription');
elD.innerHTML = lienifier(desc);
elD.style.display = desc ? '' : 'none';
var conteneurLiens = document.getElementById('modalDetailLiens');
conteneurLiens.innerHTML = '';
var liens = [];
for (var i = 1; i <= 3; i++) {
var url = el.getAttribute('data-lien' + i + '-url') || '';
if (url) {
var label = el.getAttribute('data-lien' + i + '-label') || '';
liens.push({ label: label || "Voir l'affiche / plus d'infos", url: url });
}
}
if (liens.length === 0) {
var lienHerite = el.getAttribute('data-lien') || '';
if (lienHerite) { liens.push({ label: "Voir l'affiche / plus d'infos", url: lienHerite }); }
}
liens.forEach(function(l) {
var a = document.createElement('a');
a.href = l.url;
a.target = '_blank';
a.rel = 'noopener';
a.textContent = l.label + ' →';
conteneurLiens.appendChild(a);
});
document.getElementById('modalDetailEvt').classList.add('open');
}
function fermerDetailEvt() {
document.getElementById('modalDetailEvt').classList.remove('open');
}
document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { fermerDetailEvt(); } });
</script>
{{*</body>
</html>
*}}
{{*:debug*}}
{{if $est_admin==true}}
{{:admin_footer}}
{{/if}}
+77
View File
@@ -0,0 +1,77 @@
{{* ---------- Gestion des calendriers (ajout / suppression, admin) ---------- *}}
{{#form on="add_calendrier"}}
{{if $_POST.add_calendrier && $est_admin}}
{{* Nom déjà existant ? *}}
{{if $_POST.nom_calendrier}}
{{#load where="$$.type = 'calendrier' AND $$.nom = '%s'"|args:$_POST.nom_calendrier}}
{{:error message="Le nom du calendrier existe déjà."}}
{{/load}}
{{else}}
{{:error message="Le nom du calendrier doit être renseigné."}}
{{/if}}
{{if $_POST.pardefaut == true}}
{{* enlève le flag à un des autres calendriers *}}
{{#load where="$$.type = 'calendrier' AND $$.par_defaut = true"|args:$_POST.nom_calendrier}}
{{:assign var="_id_cal" value=$id}}
{{/load}}
{{if $_id_cal}}
{{:save type="calendrier" id=$_id_cal par_defaut=false}}
{{/if}}
{{:assign _pardef=true}}
{{else}}
{{:assign _pardef=false}}
{{/if}}
{{:save type="calendrier" nom=$_POST.nom_calendrier par_defaut=$_pardef couleur=$_POST.couleur}}
{{:redirect url="index.html?nav=conf&conf=manage_cal&msg=ajout"}}
{{/if}}
{{else}}
{{:form_errors}}
{{/form}}
{{* Modifier un calendrier *}}
{{#form on="mod_calendrier"}}
{{:debug p=$_POST}}
{{* vérifications *}}
{{if !$_POST.mod_calendrier && !$est_admin}}
{{:error message="Le calendrier n'existe pas."}}
{{/if}}
{{* Nom déjà existant ? *}}
{{if $_POST.nom_calendrier}}
{{#load where="$$.type = 'calendrier' AND $$.nom = '%s' AND id <> %d"|args:$_POST.nom_calendrier:$_POST.mod_calendrier}}
{{:error message="Le nom du calendrier existe déjà."}}
{{/load}}
{{else}}
{{:error message="Le nom du calendrier doit être renseigné."}}
{{/if}}
{{* Par défaut déjà existant ? *}}
{{if $_POST.pardefaut == true}}
{{* enlève le flag à un des autres calendriers *}}
{{#load where="$$.type = 'calendrier' AND $$.par_defaut = true"|args:$_POST.nom_calendrier}}
{{:assign var="_id_cal" value=$id}}
{{/load}}
{{if $_id_cal}}
{{:save type="calendrier" id=$_id_cal par_defaut=false}}
{{/if}}
{{:assign _pardef=true}}
{{else}}
{{:assign _pardef=false}}
{{/if}}
{{:save type="calendrier" id=$_POST.mod_calendrier nom=$_POST.nom_calendrier par_defaut=$_pardef couleur=$_POST.couleur textecouleur=$_POST.couleur_texte categorie=$_POST.categorie}}
{{else}}
{{:form_errors}}
{{/form}}
{{* Supprimer un calendrier *}}
{{if $_POST.suppr_calendrier && $est_admin}}
{{:assign var="cal_a_suppr" value=$_POST.suppr_calendrier|strval|trim}}
{{:assign var="where_reassign" value="$$.calendrier = '%s'"|args:$cal_a_suppr}}
{{#load where=$where_reassign}}
{{if $type == "event"}}
{{:save id=$id type="event" titre=$titre date=$date debut=$debut fin=$fin lieu=$lieu description=$description lien=$lien lien1_label=$lien1_label lien1_url=$lien1_url lien2_label=$lien2_label lien2_url=$lien2_url lien3_label=$lien3_label lien3_url=$lien3_url couleur=$couleur calendrier=""}}
{{elseif $type == "permanence"}}
{{:save id=$id type="permanence" jour=$jour debut=$debut fin=$fin label=$label lieu=$lieu description=$description date_debut=$date_debut date_fin=$date_fin type_recurrence=$type_recurrence semaine_du_mois=$semaine_du_mois couleur=$couleur exceptions=$exceptions calendrier=""}}
{{/if}}
{{/load}}
{{:delete id=$cal_a_suppr|intval}}
{{:redirect url="index.html?nav=conf&conf=manage_cal&msg=suppression"}}
{{/if}}
+41
View File
@@ -0,0 +1,41 @@
{{* ---------- Ajout ou Modification d'un événement (admin) ---------- *}}
{{#form on="save_event" }}
{{if $_POST.save_event && $est_admin}}
{{if !$_POST.event_id}}
{{:assign var="_eventKey" value="%s"|uuid}}
{{#load where="id = %d"|args:$_POST.calendrier}}
{{:assign var="_eventColor" value=$couleur}}
{{/load}}
{{else}}
{{:assign var="_eventKey" value=$_POST.save_event}}
{{:assign var="_eventColor" value=$_POST.couleur}}
{{/if}}
{{:debug post=$_POST _eventKey=$_eventKey _eventColor=$_eventColor}}
{{:save
key=$_eventKey
type="event"
titre=$_POST.titre|strval|trim
date=$_POST.date|parse_date
debut=$_POST.debut|parse_time
fin=$_POST.fin|parse_time
lieu=$_POST.lieu|strval|trim
description=$_POST.description|strval|trim
lien1_label=$_POST.lien1_label|strval|trim
lien1_url=$_POST.lien1_url|strval|trim
lien2_label=$_POST.lien2_label|strval|trim
lien2_url=$_POST.lien2_url|strval|trim
lien3_label=$_POST.lien3_label|strval|trim
lien3_url=$_POST.lien3_url|strval|trim
couleur=$_eventColor|intval
calendrier=$_POST.calendrier|strval|trim}}
{{:redirect url="?an=%s&mois=%s"|args:$_POST.retour_an:$_POST.retour_mois}}
{{/if}}
{{else}}
{{:form_errors}}
{{/form}}
{{* ---------- Suppression d'un événement (admin) ---------- *}}
{{if $_POST.suppr_event && $est_admin}}
{{:delete id=$_POST.suppr_event|intval}}
{{:redirect url="index.html?an=%s&mois=%s"|args:$_POST.retour_an:$_POST.retour_mois}}
{{/if}}
+25
View File
@@ -0,0 +1,25 @@
{{* ---------- Suppression d'une seule occurrence (date) d'un rendez-vous régulier ---------- *}}
{{if $_POST.suppr_occurrence && $est_admin}}
{{:assign var="perm_id" value=$_POST.perm_id|intval}}
{{:assign var="date_exclue" value=$_POST.date_exclue|strval|trim}}
{{#load id=$perm_id}}
{{:assign var="ov_jour" value=$jour}}
{{:assign var="ov_debut" value=$debut}}
{{:assign var="ov_fin" value=$fin}}
{{:assign var="ov_label" value=$label}}
{{:assign var="ov_date_debut" value=$date_debut}}
{{:assign var="ov_date_fin" value=$date_fin}}
{{:assign var="ov_type_recurrence" value=$type_recurrence}}
{{:assign var="ov_semaine_du_mois" value=$semaine_du_mois}}
{{:assign var="ov_couleur" value=$couleur}}
{{:assign var="ov_lieu" value=$lieu}}
{{:assign var="ov_description" value=$description}}
{{:assign var="ov_calendrier" value=$calendrier}}
{{#foreach from=$exceptions item="ex"}}
{{:assign var="new_exceptions." value=$ex}}
{{/foreach}}
{{/load}}
{{:assign var="new_exceptions." value=$date_exclue}}
{{:save id=$perm_id type="permanence" jour=$ov_jour debut=$ov_debut fin=$ov_fin label=$ov_label lieu=$ov_lieu description=$ov_description date_debut=$ov_date_debut date_fin=$ov_date_fin type_recurrence=$ov_type_recurrence semaine_du_mois=$ov_semaine_du_mois couleur=$ov_couleur calendrier=$ov_calendrier exceptions=$new_exceptions}}
{{:redirect url="index.html?an=%s&mois=%s"|args:$_POST.retour_an:$_POST.retour_mois}}
{{/if}}
+23
View File
@@ -0,0 +1,23 @@
{{* ---------- Ajout d'une permanence récurrente ---------- *}}
{{if $_POST.add_perm && $est_admin}}
{{:assign var="lbl" value=$_POST.label|strval|trim}}
{{if $lbl != ""}}
{{:save type="permanence" jour=$_POST.jour|intval debut=$_POST.debut|strval|trim fin=$_POST.fin|strval|trim label=$lbl lieu=$_POST.lieu|strval|trim description=$_POST.description|strval|trim date_debut=$_POST.date_debut|strval|trim date_fin=$_POST.date_fin|strval|trim type_recurrence=$_POST.type_recurrence|strval|trim semaine_du_mois=$_POST.semaine_du_mois|intval couleur=$_POST.couleur|strval|trim calendrier=$_POST.calendrier|strval|trim}}
{{:redirect url="index.html"}}
{{/if}}
{{/if}}
{{* ---------- Modification d'une permanence ---------- *}}
{{if $_POST.rename_perm && $est_admin}}
{{:assign var="lbl" value=$_POST.label|strval|trim}}
{{if $lbl != ""}}
{{:save id=$_POST.rename_perm|intval type="permanence" jour=$_POST.jour|intval debut=$_POST.debut|strval|trim fin=$_POST.fin|strval|trim label=$lbl lieu=$_POST.lieu|strval|trim description=$_POST.description|strval|trim date_debut=$_POST.date_debut|strval|trim date_fin=$_POST.date_fin|strval|trim type_recurrence=$_POST.type_recurrence|strval|trim semaine_du_mois=$_POST.semaine_du_mois|intval couleur=$_POST.couleur|strval|trim calendrier=$_POST.calendrier|strval|trim}}
{{:redirect url="index.html"}}
{{/if}}
{{/if}}
{{* ---------- Suppression d'une permanence ---------- *}}
{{if $_POST.suppr_perm && $est_admin}}
{{:delete id=$_POST.suppr_perm|intval}}
{{:redirect url="index.html"}}
{{/if}}
+12
View File
@@ -0,0 +1,12 @@
name = "Agenda"
description = "Gestion des calendriers associatif avec vues mensuel/semaine/liste, rendez-vous réguliers récurrents (avec exceptions et couleurs), événements ponctuels, purge et tri automatiques. \nversion 1.1"
author = "Vive le Vélo (original) / Recycl'arz"
author_url = "https://git.kaz.bzh/bountz/agenda"
restrict_section = "web"
restrict_level = "write"
home_button = false
menu = true
config = null
enabled = false
web = false
system = false
+15
View File
@@ -0,0 +1,15 @@
{{:assign var="aujourdhui" value=$now|date:"Y-m-d"}}
{{:assign var="where_public" value="$$.type = 'calendrier' AND $$.categorie = 'p' "}}
{{:assign var="event_trouve" value=false}}
<h4>Prochains événements</h4>
<ul>
{{#load module="agenda" where=$where_public limit=1}}
{{:assign var="where_venir" value="$$.type = 'event' AND $$.date >= '%s' AND $$.calendrier = '%s' "|args:$aujourdhui:$id}}
{{/load}}
{{#load module="agenda" where=$where_venir order="$$.date ASC" limit=4}}
{{:assign var="event_trouve" value=true}}
<li><b>{{$date|date_short}}</b> {{$titre}}</li>
{{/load}}
</ul>
{{if !$event_trouve}}<p>Aucun événement à venir pour l'instant.</p>{{/if}}