Skip to content

Commit 39abc52

Browse files
committed
frontend changes
1 parent 5963bb0 commit 39abc52

File tree

11 files changed

+1296
-1147
lines changed

11 files changed

+1296
-1147
lines changed
Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,77 @@
1-
@inject ExerciseClient ExerciseClient
1+
@using GradeManagement.Client.Components.NewDialogs
2+
@inject IDialogService DialogService
3+
@inject ExerciseClient ExerciseClient
24

3-
<MudDataGrid T="ExerciseResponse" Items="Values" EditMode="DataGridEditMode.Form" ReadOnly="false" CommittedItemChanges="@CommittedItemChanges" Style="width: 100%">
5+
<MudDataGrid T="ExerciseResponse"
6+
Items="Values"
7+
Style="width: 100%">
48
<Columns>
59
<PropertyColumn Property="x => x.Id" Title="Id" Editable="false"/>
610
<PropertyColumn Property="x => x.Name" Title="Name"/>
7-
<PropertyColumn Property="x => x.GithubPrefix" Title="Github Prefix"/>
8-
<PropertyColumn Property="x => x.ClassroomUrl" Title="Github Classroom URL"/>
11+
<PropertyColumn Property="x => x.GithubPrefix" Title="GitHub Prefix"/>
12+
<PropertyColumn Property="x => x.ClassroomUrl" Title="GitHub Classroom URL"/>
913
<PropertyColumn Property="x => x.MoodleScoreNamePrefix" Title="Moodle Score Name Prefix"/>
1014
<PropertyColumn Property="x => x.DueDate" Title="Due Date"/>
1115
<PropertyColumn Property="x => JoinScoreTypes(x)" Title="Score Types"/>
12-
<DataGridActions TItem="ExerciseResponse" OnEditItem="@StartEditing" OnDeleteItem="@DeleteItem"/>
16+
17+
<TemplateColumn>
18+
<CellTemplate>
19+
<MudButton Icon="@Icons.Material.Filled.Edit" OnClick="@(() => EditExercise(context))"/>
20+
</CellTemplate>
21+
</TemplateColumn>
1322
</Columns>
14-
</MudDataGrid>
1523

24+
</MudDataGrid>
1625

1726
@code {
1827
[Parameter] public ICollection<ExerciseResponse> Values { get; set; }
1928

20-
private string JoinScoreTypes(ExerciseResponse item) => string.Join(", ", item.ScoreTypes.Select(x => $"{x.Key}: {x.Value}"));
29+
private string JoinScoreTypes(ExerciseResponse item) =>
30+
string.Join(", ", item.ScoreTypes.Select(x => $"{x.Key}: {x.Value}"));
2131

22-
private async Task StartEditing(CellContext<ExerciseResponse?> context)
32+
private async Task EditExercise(CellContext<ExerciseResponse?> context)
2333
{
24-
await context.Actions.StartEditingItemAsync();
25-
StateHasChanged();
26-
}
34+
var item = context.Item;
35+
if (item == null) return;
2736

28-
private async Task CommittedItemChanges(ExerciseResponse items)
29-
{
30-
await ExerciseClient.UpdateAsync(items.Id, items.ToRequest());
37+
var parameters = new DialogParameters
38+
{
39+
["value"] = item.ToRequest()
40+
};
41+
42+
var dialog = DialogService.Show<NewExerciseDialog>("Edit Exercise", parameters);
43+
var result = await dialog.Result;
44+
45+
if (!result.Canceled && result.Data is ExerciseRequest updated)
46+
{
47+
var updatedResponse = await ExerciseClient.UpdateAsync(item.Id, updated);
48+
49+
var index = Values.ToList().FindIndex(x => x.Id == item.Id);
50+
if (Values is List<object> list && index >= 0 && index < list.Count)
51+
{
52+
list[index] = updatedResponse;
53+
}
54+
55+
StateHasChanged();
56+
}
3157
}
3258

33-
private async Task DeleteItem(ExerciseResponse item)
59+
private async Task DeleteExercise(CellContext<ExerciseResponse?> context)
3460
{
35-
Values.Remove(item);
36-
await ExerciseClient.DeleteAsync(item.Id);
37-
StateHasChanged();
61+
var item = context.Item;
62+
if (item == null) return;
63+
64+
var confirm = await DialogService.ShowMessageBox(
65+
"Delete Confirmation",
66+
$"Delete '{item.Name}'?",
67+
yesText: "Yes", cancelText: "No");
68+
69+
if (confirm is true)
70+
{
71+
Values.Remove(item);
72+
await ExerciseClient.DeleteAsync(item.Id);
73+
StateHasChanged();
74+
}
3875
}
3976

4077
}

grade-management-new/GradeManagement.Client/Components/Helpers/SubjectExtension.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public static ExerciseRequest ToRequest(this ExerciseResponse exercise)
4646
Name = exercise.Name,
4747
DueDate = exercise.DueDate,
4848
GithubPrefix = exercise.GithubPrefix,
49-
ScoreTypes = exercise.ScoreTypes
49+
ScoreTypes = exercise.ScoreTypes,
50+
ClassroomUrl = exercise.ClassroomUrl,
51+
MoodleScoreNamePrefix = exercise.MoodleScoreNamePrefix
5052
};
5153
}
5254

grade-management-new/GradeManagement.Client/Components/NewDialogs/NewCourseDialog.razor

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
<MudDialog>
1+
<MudDialog MaxWidth="MaxWidth.Large" FullWidth="true">
22
<TitleContent>
33
<MudText Typo="Typo.h4">New Course</MudText>
44
</TitleContent>
55
<DialogContent>
66
<MudForm @ref="form" Model="@Value" @bind-IsValid="@success" @bind-Errors="@errors">
7-
<MudTextField T="string" Label="Name" For="@(() => Value.Name)" @bind-Value="Value.Name" Required="true"></MudTextField>
8-
<MudTextField T="string" Label="Moodle Course Id" @bind-Value="@Value.MoodleCourseId" Required="true"></MudTextField>
7+
<MudTextField T="string" Label="Name" For="@(() => Value.Name)" @bind-Value="Value.Name"
8+
Required="true"></MudTextField>
9+
<MudTextField T="string" Label="Moodle Client ID" @bind-Value="@Value.MoodleClientId"
10+
Required="true"></MudTextField>
911
<SelectSemester @bind-Value="@Value.Semester"/>
1012
<SelectLanguage @bind-Value="@Value.Language"/>
1113
</MudForm>
@@ -23,7 +25,7 @@
2325
private bool success;
2426
private string[] errors;
2527

26-
[Parameter] public Course Value { get; set; } = new Course();
28+
[Parameter] public CourseRequest Value { get; set; } = new CourseRequest();
2729

2830
void Submit() => MudDialog.Close(DialogResult.Ok(Value));
2931
void Cancel() => MudDialog.Cancel();

grade-management-new/GradeManagement.Client/Components/NewDialogs/NewExerciseDialog.razor

Lines changed: 88 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,39 @@
33
<MudText Typo="Typo.h4">New Exercise</MudText>
44
</TitleContent>
55
<DialogContent>
6-
<MudForm @ref="form" Model="@value" @bind-IsValid="@success" @bind-Errors="@errors">
7-
<MudTextField T="string" Label="Name" For="@(() => value.Name)" @bind-Value="value.Name" Required="true"></MudTextField>
8-
<MudTextField T="string" Label="GitHub Prefix" For="@(() => value.GithubPrefix)" @bind-Value="value.GithubPrefix" Required="true"></MudTextField>
9-
<MudTextField T="string" Label="GitHub Classroom URL" For="@(() => value.ClassroomUrl)" @bind-Value="value.ClassroomUrl" Required="true"></MudTextField>
10-
<MudTextField T="string" Label="Moodle score name prefix" For="@(() => value.MoodleScoreNamePrefix)" @bind-Value="value.MoodleScoreNamePrefix" Required="true"></MudTextField>
11-
@* <MudTextField T="string" Label="Github Prefix" For="@(() => value.DueDate)" @bind-Value="value.DueDate" Required="true"></MudTextField> *@
12-
@* <MudTextField T="string" Label="Github Prefix" For="@(() => value.ScoreTypes)" @bind-Value="value.ScoreTypes" Required="true"></MudTextField> *@
6+
<MudForm @ref="form" Model="@Value" @bind-IsValid="@success" @bind-Errors="@errors">
7+
<MudTextField T="string" Label="Name" For="@(() => Value.Name)" @bind-Value="Value.Name" Required="true"/>
8+
<MudTextField T="string" Label="GitHub Prefix" For="@(() => Value.GithubPrefix)"
9+
@bind-Value="Value.GithubPrefix" Required="true"/>
10+
<MudTextField T="string" Label="GitHub Classroom URL" For="@(() => Value.ClassroomUrl)"
11+
@bind-Value="Value.ClassroomUrl" Required="true"/>
12+
<MudTextField T="string" Label="Moodle score name prefix" For="@(() => Value.MoodleScoreNamePrefix)"
13+
@bind-Value="Value.MoodleScoreNamePrefix" Required="true"/>
1314
</MudForm>
15+
16+
<MudDivider Class="my-4"/>
17+
<MudText Typo="Typo.h6">Score Types</MudText>
18+
<MudStack Spacing="2">
19+
@foreach (var item in OrderedScoreTypes.Select((kvp, index) => new { kvp.Key, kvp.Value, index }))
20+
{
21+
<MudPaper Class="p-2 d-flex align-items-center justify-content-between">
22+
<MudTextField T="string" Class="me-2" Value="@item.Value"
23+
ValueChanged="val => UpdateScoreType(item.index, val)"/>
24+
<MudIconButton Icon="@Icons.Material.Filled.ArrowUpward" Disabled="@(item.index == 0)"
25+
OnClick="@(() => MoveScoreTypeUp(item.index))"/>
26+
<MudIconButton Icon="@Icons.Material.Filled.ArrowDownward"
27+
Disabled="@(item.index == OrderedScoreTypes.Count - 1)"
28+
OnClick="@(() => MoveScoreTypeDown(item.index))"/>
29+
<MudIconButton Icon="@Icons.Material.Filled.Delete" OnClick="@(() => RemoveScoreType(item.index))"
30+
Color="Color.Error"/>
31+
</MudPaper>
32+
}
33+
34+
<MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="AddScoreType">
35+
<MudIcon Icon="@Icons.Material.Filled.Add"/>
36+
Add Score Type
37+
</MudButton>
38+
</MudStack>
1439
</DialogContent>
1540
<DialogActions>
1641
<MudButton OnClick="@Cancel">Cancel</MudButton>
@@ -25,7 +50,14 @@
2550
private bool success;
2651
private string[] errors;
2752

28-
private void Submit() => MudDialog.Close(DialogResult.Ok(value));
53+
[Parameter]
54+
public ExerciseRequest Value { get; set; } = new()
55+
{
56+
DueDate = DateTime.Now,
57+
ScoreTypes = new Dictionary<string, string>()
58+
};
59+
60+
private void Submit() => MudDialog.Close(DialogResult.Ok(Value));
2961
private void Cancel() => MudDialog.Cancel();
3062

3163
async void OnSubmitClicked()
@@ -37,10 +69,54 @@
3769
}
3870
}
3971

40-
public ExerciseRequest value = new()
72+
// ScoreTypes Logic
73+
private List<KeyValuePair<string, string>> OrderedScoreTypes =>
74+
Value.ScoreTypes.OrderBy(kvp => int.Parse(kvp.Key)).ToList();
75+
76+
private void AddScoreType()
4177
{
42-
DueDate = DateTime.Now,
43-
ScoreTypes = new Dictionary<string, string>()
44-
};
78+
int nextKey = Value.ScoreTypes.Count + 1;
79+
Value.ScoreTypes[nextKey.ToString()] = "";
80+
}
81+
82+
private void RemoveScoreType(int index)
83+
{
84+
var list = OrderedScoreTypes;
85+
if (index < 0 || index >= list.Count) return;
86+
87+
list.RemoveAt(index);
88+
ReorderScoreTypes(list);
89+
}
90+
91+
private void MoveScoreTypeUp(int index)
92+
{
93+
if (index <= 0) return;
94+
var list = OrderedScoreTypes;
95+
(list[index - 1], list[index]) = (list[index], list[index - 1]);
96+
ReorderScoreTypes(list);
97+
}
98+
99+
private void MoveScoreTypeDown(int index)
100+
{
101+
var list = OrderedScoreTypes;
102+
if (index >= list.Count - 1) return;
103+
(list[index + 1], list[index]) = (list[index], list[index + 1]);
104+
ReorderScoreTypes(list);
105+
}
106+
107+
private void UpdateScoreType(int index, string newValue)
108+
{
109+
var list = OrderedScoreTypes;
110+
var pair = list[index];
111+
list[index] = new KeyValuePair<string, string>(pair.Key, newValue);
112+
ReorderScoreTypes(list);
113+
}
114+
115+
private void ReorderScoreTypes(List<KeyValuePair<string, string>> list)
116+
{
117+
Value.ScoreTypes = list
118+
.Select((kvp, idx) => new KeyValuePair<string, string>((idx + 1).ToString(), kvp.Value))
119+
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
120+
}
45121

46122
}

0 commit comments

Comments
 (0)