updated events to remove duplicates when edit reccurring
This commit is contained in:
@@ -199,14 +199,56 @@ router.get('/', authMiddleware, async (req, res) => {
|
||||
if (to) { sql += ` AND start_at <= $${pi++}`; params.push(to); }
|
||||
sql += ' ORDER BY start_at ASC';
|
||||
const rawEvents = await query(req.schema, sql, params);
|
||||
const events = [];
|
||||
|
||||
// Separate master events and exception instances
|
||||
const masterEvents = [];
|
||||
const exceptionInstances = [];
|
||||
for (const e of rawEvents) {
|
||||
if (e.recurring_master_id) {
|
||||
exceptionInstances.push(e);
|
||||
} else {
|
||||
masterEvents.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a map of exception dates by master event
|
||||
const exceptionDatesByMaster = new Map();
|
||||
for (const exc of exceptionInstances) {
|
||||
if (!exceptionDatesByMaster.has(exc.recurring_master_id)) {
|
||||
exceptionDatesByMaster.set(exc.recurring_master_id, new Set());
|
||||
}
|
||||
const dateStr = new Date(exc.original_start_at || exc.start_at).toISOString().split('T')[0];
|
||||
exceptionDatesByMaster.get(exc.recurring_master_id).add(dateStr);
|
||||
}
|
||||
|
||||
const events = [];
|
||||
for (const e of masterEvents) {
|
||||
// Skip master events if all their occurrences in range are replaced by exceptions
|
||||
if (e.recurrence_rule && exceptionDatesByMaster.has(e.id)) {
|
||||
const exceptions = exceptionDatesByMaster.get(e.id);
|
||||
const rule = e.recurrence_rule;
|
||||
|
||||
// Check if this is a simple case where all occurrences are replaced
|
||||
// For now, we'll include the master and let frontend handle filtering
|
||||
// This is safer to avoid missing edge cases
|
||||
}
|
||||
|
||||
if (!(await canViewEvent(req.schema, e, req.user.id, itm))) continue;
|
||||
await enrichEvent(req.schema, e);
|
||||
const mine = await queryOne(req.schema, 'SELECT response FROM event_availability WHERE event_id=$1 AND user_id=$2', [e.id, req.user.id]);
|
||||
const mine = await queryOne(req.schema, 'SELECT response FROM event_availability WHERE event_id=$1 AND user_id=$2', [e.id]);
|
||||
e.my_response = mine?.response || null;
|
||||
events.push(e);
|
||||
}
|
||||
|
||||
// Add exception instances (they're standalone events)
|
||||
for (const e of exceptionInstances) {
|
||||
if (!(await canViewEvent(req.schema, e, req.user.id, itm))) continue;
|
||||
await enrichEvent(req.schema, e);
|
||||
const mine = await queryOne(req.schema, 'SELECT response FROM event_availability WHERE event_id=$1 AND user_id=$2', [e.id]);
|
||||
e.my_response = mine?.response || null;
|
||||
events.push(e);
|
||||
}
|
||||
|
||||
res.json({ events });
|
||||
} catch (e) { res.status(500).json({ error: e.message }); }
|
||||
});
|
||||
|
||||
2
build.sh
2
build.sh
@@ -16,7 +16,7 @@ set -euo pipefail
|
||||
VERSION="${1:-0.12.37}"
|
||||
ACTION="${2:-}"
|
||||
REGISTRY="${REGISTRY:-}"
|
||||
IMAGE_NAME="rosterchirp"
|
||||
IMAGE_NAME="rosterchirp-dev"
|
||||
|
||||
# If a registry is set, prefix image name
|
||||
if [[ -n "$REGISTRY" ]]; then
|
||||
|
||||
@@ -1125,14 +1125,57 @@ function expandRecurringEvent(ev, rangeStart, rangeEnd) {
|
||||
// Expand all recurring events in a list within a date range
|
||||
function expandEvents(events, rangeStart, rangeEnd) {
|
||||
const result = [];
|
||||
|
||||
// First, collect all exception instances and their dates by master event
|
||||
const exceptionDatesByMaster = new Map();
|
||||
const masterEvents = [];
|
||||
const standaloneEvents = [];
|
||||
|
||||
for (const ev of events) {
|
||||
if (ev.recurrence_rule?.freq) {
|
||||
const expanded = expandRecurringEvent(ev, rangeStart, rangeEnd);
|
||||
result.push(...expanded);
|
||||
if (ev.recurring_master_id) {
|
||||
// This is an exception instance
|
||||
if (!exceptionDatesByMaster.has(ev.recurring_master_id)) {
|
||||
exceptionDatesByMaster.set(ev.recurring_master_id, new Set());
|
||||
}
|
||||
const dateStr = new Date(ev.original_start_at || ev.start_at).toISOString().split('T')[0];
|
||||
exceptionDatesByMaster.get(ev.recurring_master_id).add(dateStr);
|
||||
standaloneEvents.push(ev); // Exception instances are standalone events
|
||||
} else if (ev.recurrence_rule?.freq) {
|
||||
masterEvents.push(ev);
|
||||
} else {
|
||||
result.push(ev);
|
||||
standaloneEvents.push(ev);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand master events, skipping dates that have exception instances
|
||||
for (const ev of masterEvents) {
|
||||
const exceptions = exceptionDatesByMaster.get(ev.id);
|
||||
if (exceptions) {
|
||||
// Merge the rule's exceptions with the instance exceptions
|
||||
const rule = ev.recurrence_rule || {};
|
||||
const ruleExceptions = new Set(rule.exceptions || []);
|
||||
for (const date of exceptions) {
|
||||
ruleExceptions.add(date);
|
||||
}
|
||||
// Create a copy of the event with merged exceptions
|
||||
const evWithMergedExceptions = {
|
||||
...ev,
|
||||
recurrence_rule: {
|
||||
...rule,
|
||||
exceptions: Array.from(ruleExceptions)
|
||||
}
|
||||
};
|
||||
const expanded = expandRecurringEvent(evWithMergedExceptions, rangeStart, rangeEnd);
|
||||
result.push(...expanded);
|
||||
} else {
|
||||
const expanded = expandRecurringEvent(ev, rangeStart, rangeEnd);
|
||||
result.push(...expanded);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all standalone events (non-recurring + exception instances)
|
||||
result.push(...standaloneEvents);
|
||||
|
||||
// Sort by start_at
|
||||
result.sort((a,b) => new Date(a.start_at) - new Date(b.start_at));
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user