feat(todo): a project linked to a calendar shows its events beside the tasks (ADR 0033, D39)
A project's editor takes a calendar's address (https:// or webcal://, refused otherwise), and its events show read-only, marked in the project's colour: in Today's list and Upcoming's agenda above each day's tasks, as blocks in the hour grids (Today's Calendar, Upcoming's 3-day) sharing the lanes with timed tasks and all-day ones under All day, in the project's Calendar (its agenda and month, its own events alone), and in saved filters of days. A tap shows what an event is: when, where, and whose calendar. The grid's lane layout is generic for it (`layOutItems`); a task's row's box is shared (`rowBox`). Whats-New: Link a calendar to a project in its settings: its events show beside your tasks in Today, Upcoming and the project. Whats-New-De: Verknüpfe einen Kalender in den Einstellungen eines Projekts: Seine Termine erscheinen neben deinen Aufgaben in Heute, Demnächst und im Projekt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
63d50f77d4
commit
85a022af98
2 changed files with 1032 additions and 83 deletions
|
|
@ -0,0 +1,74 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/calendar/bloc/calendar_cubit.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/calendar/model/ical.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/filter/model/filter_events.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/filter/model/filter_query.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/task.dart';
|
||||
|
||||
/// Which events of a calendar linked to a project a saved filter shows
|
||||
/// (ADR 0033, D39): those its days take, by their project and day.
|
||||
void main() {
|
||||
const today = Day(2026, 11, 10);
|
||||
const world = FilterWorld(
|
||||
today: today,
|
||||
projects: {
|
||||
'school': (name: 'School', parentId: null),
|
||||
'home': (name: 'Home', parentId: null),
|
||||
},
|
||||
);
|
||||
|
||||
FeedEvent maths(Day day, {String projectId = 'school'}) => FeedEvent(
|
||||
projectId,
|
||||
IcalEvent(
|
||||
uid: 'maths',
|
||||
title: 'Maths',
|
||||
start: DateTime(day.year, day.month, day.day, 9),
|
||||
end: DateTime(day.year, day.month, day.day, 10),
|
||||
),
|
||||
);
|
||||
|
||||
bool takes(String query, FeedEvent event, Day day) =>
|
||||
switch (FilterQuery.parse(query)) {
|
||||
FilterRead(:final query) => filterTakesEvent(query, event, day, world),
|
||||
FilterUnread() => fail('$query not read'),
|
||||
};
|
||||
|
||||
test('a filter of days takes the events on them, of its projects', () {
|
||||
expect(takes('today', maths(today), today), isTrue);
|
||||
expect(takes('today', maths(today.plus(1)), today.plus(1)), isFalse);
|
||||
expect(
|
||||
takes('7 days & #School', maths(today.plus(2)), today.plus(2)),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
takes('7 days & #School', maths(today, projectId: 'home'), today),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('a filter not of days takes none: its project, a label, no date', () {
|
||||
expect(takes('#School', maths(today), today), isFalse);
|
||||
expect(takes('no date', maths(today), today), isFalse);
|
||||
expect(takes('p1 & today', maths(today), today), isFalse);
|
||||
});
|
||||
|
||||
test(
|
||||
'the events of the next four weeks a filter takes, each on its days',
|
||||
() {
|
||||
final events = eventsOfFilter(
|
||||
switch (FilterQuery.parse('7 days')) {
|
||||
FilterRead(:final query) => query,
|
||||
FilterUnread() => fail('not read'),
|
||||
},
|
||||
[
|
||||
for (var day = 0; day < 28; day++) [maths(today.plus(day))],
|
||||
],
|
||||
today,
|
||||
world,
|
||||
);
|
||||
expect(events.map((event) => event.$2), [
|
||||
for (var day = 0; day < 7; day++) today.plus(day),
|
||||
]);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
occurrence: false,
|
||||
);
|
||||
|
||||
String laid(List<GridBlock> blocks) => [
|
||||
String laid(List<GridBlock<CalendarEntry>> blocks) => [
|
||||
for (final b in blocks)
|
||||
'${b.entry.task.id} ${b.start}-${b.end} ${b.lane}/${b.lanes}',
|
||||
].join('; ');
|
||||
|
|
|
|||
Loading…
Reference in a new issue