Skip to content

Commit 40fb9f6

Browse files
authored
Implement personal calendar modification reset button (#202)
1 parent be5cbac commit 40fb9f6

12 files changed

Lines changed: 309 additions & 190 deletions

StartSch.Wasm/Components/EventSettingsDialog.razor

Lines changed: 188 additions & 144 deletions
Large diffs are not rendered by default.

StartSch.Wasm/Components/EventSettingsDialog.razor.css

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
.selected-event-settings {
3737
position: relative;
38+
border-radius: 8px;
39+
background-color: var(--md-sys-color-surface-container-lowest);
40+
padding: 16px;
41+
margin-top: 16px;
3842

3943
.section-label {
4044
position: absolute;
@@ -58,10 +62,13 @@
5862
margin-bottom: 8px;
5963
}
6064
}
61-
62-
border-radius: 8px;
63-
background-color: var(--md-sys-color-surface-container-lowest);
64-
padding: 16px;
65-
margin-top: 16px;
65+
66+
.option-with-reset-button {
67+
&:has(.reset-button) {
68+
display: grid;
69+
grid-template-columns: 1fr auto;
70+
gap: 8px;
71+
}
72+
}
6673
}
6774
}

StartSch.Wasm/Components/PersonalCalendarConfigurator.razor

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@using StartSch.Wasm.PersonalCalendars
66
@inject HttpClient HttpClient
77
@inject NavigationManager NavigationManager
8+
@inject IJSRuntime Js
89
@rendermode InteractiveWebAssemblyWithoutPrerendering
910

1011
<div class="root">
@@ -38,7 +39,7 @@
3839
var fullCalendarEvents = events.Select(eventContext =>
3940
{
4041
var e = _applyModifications ? eventContext.ModifiedEvent : eventContext.OriginalEvent;
41-
var category = e.CategoryCalendar;
42+
var category = e.CategoryCalendarOrDefault;
4243
return new FullCalendarEvent(
4344
e.Id,
4445
e.Start.ToDateTimeOffset(),
@@ -125,7 +126,7 @@
125126

126127
protected override void OnInitialized()
127128
{
128-
_welcome = NavigationManager.Uri.Contains("welcome");
129+
_welcome = NavigationManager.Uri.EndsWith("#welcome");
129130
_isSettingsOpen = _welcome;
130131

131132
_editorToken = EditorToken;
@@ -147,6 +148,14 @@
147148
}
148149
}
149150

151+
protected override async Task OnAfterRenderAsync(bool firstRender)
152+
{
153+
if (!firstRender || !_welcome)
154+
return;
155+
var newUri = NavigationManager.Uri.RemoveFromEnd("#welcome").ToString();
156+
await Js.InvokeVoidAsync("history.replaceState", null, "", newUri);
157+
}
158+
150159
private async Task Save(PersonalCalendarLive calendar)
151160
{
152161
using var responseMessage = await HttpClient.PutAsJsonAsync(
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@if (!IsVisible) return;
2+
3+
<md-icon-button @onclick="@ResetCallback" class="reset-button">
4+
<md-icon>
5+
reset_wrench
6+
</md-icon>
7+
</md-icon-button>
8+
9+
@code {
10+
[Parameter, EditorRequired] public bool IsVisible { get; set; }
11+
[Parameter, EditorRequired] public EventCallback ResetCallback { get; set; }
12+
}

StartSch.Wasm/PersonalCalendars/EventContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ private PersonalCalendarEvent CreateModifiedEvent()
1818
var modifiedEvent = OriginalEvent.Copy();
1919
foreach (var modification in _modifications)
2020
modification.Action.Apply(modifiedEvent);
21-
modifiedEvent.CategoryCalendar = modifiedEvent.CategoryCalendarId is { } categoryCalendarId
21+
modifiedEvent.CategoryCalendarOrDefault = modifiedEvent.CategoryCalendarId is { } categoryCalendarId
2222
? getCategoryById(categoryCalendarId)
2323
: null;
2424
return modifiedEvent;

StartSch.Wasm/PersonalCalendars/IModificationTarget.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public interface IModificationTarget
1212
/// Updates the target, such that the given event is no longer matched
1313
/// <returns>true, if there are no more targets, and the modification can therefore be garbage collected</returns>
1414
bool RemoveTarget(EventContext eventContext);
15+
16+
IModificationTarget Clone();
1517
}
1618

1719
public class CalendarAndEventIdTarget : IModificationTarget
@@ -25,6 +27,8 @@ public IReadOnlySet<EventContext> GetTargets(TargetIndex index) =>
2527
: ImmutableHashSet<EventContext>.Empty;
2628

2729
public bool RemoveTarget(EventContext eventContext) => true;
30+
31+
public IModificationTarget Clone() => new CalendarAndEventIdTarget { CalendarId = CalendarId, EventId = EventId };
2832
}
2933

3034
public class NeptunSeriesTarget : IModificationTarget
@@ -34,8 +38,7 @@ public class NeptunSeriesTarget : IModificationTarget
3438

3539
public IReadOnlySet<EventContext> GetTargets(TargetIndex index) =>
3640
SelectedDates
37-
.Select(date =>
38-
index.SubjectCourseAndDateToEvent.GetValueOrDefault((SubjectAndCourse, date)))
41+
.Select(date => index.SubjectCourseAndDateToEvent.GetValueOrDefault((SubjectAndCourse, date)))
3942
.Where(x => x != null)
4043
.Select(x => x!)
4144
.ToImmutableHashSet();
@@ -45,4 +48,10 @@ public bool RemoveTarget(EventContext eventContext)
4548
SelectedDates.Remove(eventContext.OriginalEvent.Start);
4649
return SelectedDates.Count == 0;
4750
}
51+
52+
public IModificationTarget Clone() => new NeptunSeriesTarget
53+
{
54+
SubjectAndCourse = SubjectAndCourse,
55+
SelectedDates = new(SelectedDates),
56+
};
4857
}

StartSch.Wasm/PersonalCalendars/PersonalCalendarContext.cs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,15 @@ public PersonalCalendarContext(PersonalCalendarContextDto dto)
5454
AddOriginalEvents(calendar, calendar.Events);
5555

5656
foreach (var modification in config.Modifications)
57-
foreach (var eventContext in modification.Target.GetTargets(_targetIndex))
58-
eventContext.AddModification(modification);
57+
foreach (var eventContext in modification.Target.GetTargets(_targetIndex))
58+
eventContext.AddModification(modification);
5959

6060
foreach (var eventIndexEntry in _eventsByStart)
6161
IndexModifiedEvent(eventIndexEntry.EventContext);
6262
}
6363

64-
private List<EventContext> AddOriginalEvents(PersonalCalendarLive sourceCalendar, IEnumerable<PersonalCalendarEvent> events)
64+
private List<EventContext> AddOriginalEvents(PersonalCalendarLive sourceCalendar,
65+
IEnumerable<PersonalCalendarEvent> events)
6566
{
6667
List<EventContext> results = [];
6768
foreach (PersonalCalendarEvent originalEvent in events)
@@ -90,22 +91,22 @@ public void ReplaceOriginalEvents(PersonalCalendarLive sourceCalendar, IEnumerab
9091
foreach (EventContext oldContext in oldContexts)
9192
{
9293
DeindexModifiedEvent(oldContext);
93-
94+
9495
var originalEvent = oldContext.OriginalEvent;
9596
_eventsByStart.Remove(new(originalEvent.Start, originalEvent.Id, oldContext));
9697
_eventsByEnd.Remove(new(originalEvent.End, originalEvent.Id, oldContext));
9798
_calIdToEvents.RemoveFromCollection(sourceCalendar.Id, oldContext);
9899
_calAndIdToEvent.Remove((sourceCalendar.Id, originalEvent.Id));
99100
_targetIndex.Remove(oldContext);
100101
}
101-
102+
102103
var newContexts = AddOriginalEvents(sourceCalendar, events);
103104
TargetIndex tempIndex = new();
104105
foreach (var eventContext in newContexts)
105106
tempIndex.Add(eventContext);
106107
foreach (var modification in _modifications)
107-
foreach (var affectedEvent in modification.Target.GetTargets(tempIndex))
108-
affectedEvent.AddModification(modification);
108+
foreach (var affectedEvent in modification.Target.GetTargets(tempIndex))
109+
affectedEvent.AddModification(modification);
109110
foreach (var eventContext in newContexts)
110111
IndexModifiedEvent(eventContext);
111112
}
@@ -171,15 +172,16 @@ public EventEditContext GetEditContext(int calendarId, string eventId)
171172
var e = _calAndIdToEvent[(cal.Id, eventId)];
172173
var time = e.OriginalEvent.Start.InZone(SharedUtils.HungarianTimeZone);
173174

174-
List<EventContext>? relatedEvents = null;
175-
if (e.OriginalEvent is { Subject: { } subject, Course: { } course })
175+
return new(e, GetRelatedEvents());
176+
177+
IRelatedEvents? GetRelatedEvents()
176178
{
177-
relatedEvents = _targetIndex.SeriesToEvents[new(new(subject, course), time.DayOfWeek, time.TimeOfDay)]
178-
.Select(x => x.EventContext)
179-
.ToList();
179+
if (e.OriginalEvent is { Subject: { } subject, Course: { } course }
180+
&& _targetIndex.SeriesToEvents[new(new(subject, course), time.DayOfWeek, time.TimeOfDay)]
181+
is { Count: > 1 } entries)
182+
return new NeptunSeriesEvents(entries.Select(x => x.EventContext).ToList(), new(subject, course));
183+
return null;
180184
}
181-
182-
return new(e, relatedEvents);
183185
}
184186

185187
public void AddModification(Modification modification)
@@ -209,13 +211,14 @@ public void AddModification(Modification modification)
209211
}
210212
}
211213

212-
public void RevertModifications(IModificationTarget target, Type actionType)
214+
public void ResetModifications(IModificationTarget target, Type actionType)
213215
{
214216
var targetEvents = target.GetTargets(_targetIndex);
215217
foreach (var eventContext in targetEvents)
216218
{
219+
var modification = eventContext.Modifications.FirstOrDefault(m => m.Action.GetType() == actionType);
220+
if (modification is null) continue;
217221
DeindexModifiedEvent(eventContext);
218-
var modification = eventContext.Modifications.First(m => m.Action.GetType() == actionType);
219222
eventContext.RemoveModification(modification);
220223
if (modification.Target.RemoveTarget(eventContext))
221224
_modifications.Remove(modification);
@@ -260,7 +263,14 @@ public int CompareTo(EventIndexEntry other)
260263
}
261264
}
262265

263-
public record EventEditContext(EventContext EventContext, List<EventContext>? RelatedEvents);
266+
public record EventEditContext(EventContext EventContext, IRelatedEvents? RelatedEvents);
267+
268+
public interface IRelatedEvents
269+
{
270+
List<EventContext> Events { get; }
271+
}
272+
273+
public record NeptunSeriesEvents(List<EventContext> Events, NeptunSubjectAndCourse SubjectAndCourse) : IRelatedEvents;
264274

265275
public readonly record struct NeptunSubjectAndCourse(string Subject, string Course);
266276

StartSch.Wasm/PersonalCalendars/PersonalCalendarEvent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class PersonalCalendarEvent
2323
public List<string>? Teachers { get; set; }
2424

2525
[JsonIgnore] public PersonalCalendarLive SourceCalendar { get; set; } = null!;
26-
[JsonIgnore] public PersonalCalendarCategoryLive? CategoryCalendar { get => field ?? GetDefaultCategory?.Invoke(); set; }
26+
[JsonIgnore] public PersonalCalendarCategoryLive? CategoryCalendarOrDefault { get => field ?? GetDefaultCategory?.Invoke(); set; }
2727
[JsonIgnore] public Func<PersonalCalendarCategoryLive>? GetDefaultCategory { get; set; }
2828

2929
public PersonalCalendarEvent Copy()
@@ -42,7 +42,7 @@ public PersonalCalendarEvent Copy()
4242
Course = Course,
4343
Teachers = Teachers?.ToList(),
4444
SourceCalendar = SourceCalendar,
45-
CategoryCalendar = CategoryCalendar,
45+
CategoryCalendarOrDefault = CategoryCalendarOrDefault,
4646
GetDefaultCategory = GetDefaultCategory,
4747
};
4848
}

StartSch/Services/FontCache.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public class FontCache
8585
"open_in_new",
8686
"publish",
8787
"reset_settings",
88+
"reset_wrench",
8889
"restaurant",
8990
"save",
9091
"save_as",

StartSch/Services/IcalendarCache.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace StartSch.Services;
1212
public class IcalendarCache(
1313
IMemoryCache memoryCache,
1414
HttpClient httpClient,
15-
PortalVikBmeHuModule portalVikBmeHuModule
15+
PortalVikBmeHuModule? portalVikBmeHuModule = null
1616
)
1717
{
1818
// TODO: return error events when URL is invalid or return an error to be handled that can then be turned into events
@@ -62,7 +62,7 @@ public async Task<List<PersonalCalendarEvent>> GetEvents(string url, Type extern
6262
if (icalendarEvent.Categories is [{ } category])
6363
{
6464
subjectId = category;
65-
subjectData = portalVikBmeHuModule.GetSubject(subjectId);
65+
subjectData = portalVikBmeHuModule?.GetSubject(subjectId);
6666
}
6767
}
6868

@@ -87,7 +87,8 @@ neptunLessonEventTitleData is { }
8787
Subject = neptunLessonEventTitleData?.Subject
8888
?? subjectData?.Name,
8989
Course = neptunLessonEventTitleData?.Course,
90-
Teachers = neptunLessonEventTitleData?.Teachers,
90+
Teachers = neptunLessonEventTitleData?.Teachers
91+
?? neptunFinalEventTitleData?.Teachers,
9192
};
9293
}
9394

0 commit comments

Comments
 (0)