feat(calendar): v5.8.0 calendrier & rappels + v5.7.0 database avancee (pt.2)
FlowDeck CI / lint (push) Successful in 49s
FlowDeck CI / test (push) Successful in 5m26s
FlowDeck CI / docker (push) Successful in 43s

v5.8.0 (release 5.11.7) — Calendrier & Rappels :
- moteur de recurrence RRULE subset (daily/weekly/monthly, interval,
  count, until, byweekday, timezone) — app/services/recurrence.py
- vues calendar Jour / Semaine / Mois avec expansion des occurrences
  cote serveur (GET /db/{id}/calendar/api) et popover evenement
  (Time / Timezone / Repeat / Remind)
- rappels avant echeance (scan 60 s, table reminder_log, in-app +
  email, cible = personnes assignees) — app/services/reminders.py
- fuseaux horaires : users.timezone + reglages in-app, timezone par
  evenement, liste de zones (GET /db/timezones/api)
- notifications d'assignation sur PUT /db/pages/{id}/api et
  preferences etendues (reminders, assignments)
- template Meeting notes enrichi (Agenda, Notes — migration 12)
- migrations 11-12 ; 20 tests dedies ; suite complete 523 verte

v5.7.0 (release 5.11.6, termine avant cette session, reste dans
l'arbre sans commit) — Database Avancée Pt.2 :
- proprietes person + auto-proprietes (created/last-edited time & by)
- groupes de proprietes, vues sauvegardees par utilisateur
- swimlanes, WIP limits, cartes configurables, calendar drag & drop,
  gallery couvertures ; 12 tests dedies
This commit is contained in:
2026-09-13 22:49:14 -04:00
parent 055956a351
commit d4adf89db5
18 changed files with 3301 additions and 366 deletions
+59 -2
View File
@@ -274,6 +274,47 @@
</label>
</div>
</div>
<div class="setting-row">
<div>
<div class="setting-label">Reminders</div>
<div class="setting-desc">Upcoming events &amp; date reminders from your databases</div>
</div>
<div class="setting-control">
<label class="toggle-switch sm">
<input type="checkbox" x-model="notifPrefs.reminders" @change="saveNotifPrefs()">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="setting-row">
<div>
<div class="setting-label">Assignments</div>
<div class="setting-desc">When a database row is assigned to you</div>
</div>
<div class="setting-control">
<label class="toggle-switch sm">
<input type="checkbox" x-model="notifPrefs.assignments" @change="saveNotifPrefs()">
<span class="toggle-slider"></span>
</label>
</div>
</div>
</div>
<div class="setting-group">
<h3>Timezone</h3>
<div class="setting-row">
<div>
<div class="setting-label">Your timezone</div>
<div class="setting-desc">Used by calendar views (today, week start) and reminder firing. Empty = UTC.</div>
</div>
<div class="setting-control">
<select class="settings-input" style="max-width:260px" x-model="userTimezone" @change="saveTimezone()">
<option value="">UTC</option>
<template x-for="z in userZones" :key="z">
<option :value="z" x-text="z"></option>
</template>
</select>
</div>
</div>
</div>
</div>
@@ -915,7 +956,8 @@ function settingsInit() {
defaultView: localStorage.getItem('fd_default_view') || 'tree',
userInfo: {full_name: '{{ user.full_name or "" }}', login: '{{ user.login or "" }}', email: '{{ user.email or "" }}'},
userIsAdmin: {{ 'true' if user.get('is_admin') else 'false' }},
notifPrefs: {comments: true, mentions: true},
notifPrefs: {comments: true, mentions: true, reminders: true, assignments: true},
userTimezone: '', userZones: [],
// Auth & Integrations
authMethod: '{{ auth_method }}',
giteaLinked: false,
@@ -984,7 +1026,13 @@ function settingsInit() {
try {
var r = await fetch('/api/notifications/prefs', {credentials:'same-origin'});
var d = await r.json();
this.notifPrefs = Object.assign({comments:true, mentions:true}, d.prefs || {});
this.notifPrefs = Object.assign({comments:true, mentions:true, reminders:true, assignments:true}, d.prefs || {});
} catch(e) {}
try {
var tz = await fetch('/api/notifications/timezone', {credentials:'same-origin'});
var td = await tz.json();
this.userTimezone = td.timezone || '';
this.userZones = td.zones || [];
} catch(e) {}
},
async saveNotifPrefs() {
@@ -995,6 +1043,15 @@ function settingsInit() {
});
} catch(e) {}
},
async saveTimezone() {
try {
var r = await fetch('/api/notifications/timezone', {
method: 'POST', headers: {'Content-Type':'application/json','X-CSRF-Token': this.getCsrfToken()},
body: JSON.stringify({timezone: this.userTimezone})
});
if (r.ok && typeof toast === 'function') toast('Timezone saved');
} catch(e) {}
},
async loadTags() {
try {