mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
removed question id
This commit is contained in:
@@ -34,102 +34,7 @@ this is my description in markdown
|
|||||||
markdown.Should().Contain("AssignmentGroup: someId");
|
markdown.Should().Contain("AssignmentGroup: someId");
|
||||||
markdown.Should().Contain("AllowedAttempts: -1");
|
markdown.Should().Contain("AllowedAttempts: -1");
|
||||||
}
|
}
|
||||||
[Test]
|
|
||||||
public void QuzMarkdownIncludesMultipleChoiceQuestion()
|
|
||||||
{
|
|
||||||
var quiz = new LocalQuiz()
|
|
||||||
{
|
|
||||||
Name = "Test Quiz",
|
|
||||||
Description = "desc",
|
|
||||||
LockAt = DateTime.MaxValue,
|
|
||||||
DueAt = DateTime.MaxValue,
|
|
||||||
ShuffleAnswers = true,
|
|
||||||
OneQuestionAtATime = false,
|
|
||||||
LocalAssignmentGroupName = "someId",
|
|
||||||
AllowedAttempts = -1,
|
|
||||||
Questions = new LocalQuizQuestion[]
|
|
||||||
{
|
|
||||||
new LocalQuizQuestion()
|
|
||||||
{
|
|
||||||
Id = "someid",
|
|
||||||
Points = 2,
|
|
||||||
Text = @"`some type` of question
|
|
||||||
|
|
||||||
with many
|
|
||||||
|
|
||||||
```
|
|
||||||
lines
|
|
||||||
```
|
|
||||||
",
|
|
||||||
QuestionType = QuestionType.MULTIPLE_CHOICE,
|
|
||||||
Answers = new LocalQuizQuestionAnswer[]
|
|
||||||
{
|
|
||||||
new LocalQuizQuestionAnswer() { Correct = true, Text = "true" },
|
|
||||||
new LocalQuizQuestionAnswer() { Correct = false, Text = "false" + Environment.NewLine +Environment.NewLine + "endline" },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var markdown = quiz.ToMarkdown();
|
|
||||||
var expectedQuestionString = @"
|
|
||||||
Points: 2
|
|
||||||
`some type` of question
|
|
||||||
|
|
||||||
with many
|
|
||||||
|
|
||||||
```
|
|
||||||
lines
|
|
||||||
```
|
|
||||||
|
|
||||||
*a) true
|
|
||||||
b) false
|
|
||||||
|
|
||||||
endline
|
|
||||||
";
|
|
||||||
markdown.Should().Contain(expectedQuestionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void QuzMarkdownIncludesMultipleAnswerQuestion()
|
|
||||||
{
|
|
||||||
var quiz = new LocalQuiz()
|
|
||||||
{
|
|
||||||
Name = "Test Quiz",
|
|
||||||
Description = "desc",
|
|
||||||
LockAt = DateTime.MaxValue,
|
|
||||||
DueAt = DateTime.MaxValue,
|
|
||||||
ShuffleAnswers = true,
|
|
||||||
OneQuestionAtATime = false,
|
|
||||||
LocalAssignmentGroupName = "someId",
|
|
||||||
AllowedAttempts = -1,
|
|
||||||
Questions = new LocalQuizQuestion[]
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = "somesdid",
|
|
||||||
Text = "oneline question",
|
|
||||||
Points = 1,
|
|
||||||
QuestionType = QuestionType.MULTIPLE_ANSWERS,
|
|
||||||
Answers = new LocalQuizQuestionAnswer[]
|
|
||||||
{
|
|
||||||
new() { Correct = true, Text = "true" },
|
|
||||||
new() { Correct = true, Text = "false"},
|
|
||||||
new() { Correct = false, Text = "neither"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var markdown = quiz.ToMarkdown();
|
|
||||||
var expectedQuestionString = @"
|
|
||||||
Points: 1
|
|
||||||
oneline question
|
|
||||||
[*] true
|
|
||||||
[*] false
|
|
||||||
[ ] neither
|
|
||||||
";
|
|
||||||
markdown.Should().Contain(expectedQuestionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCanParseMarkdownQuizWithNoQuestions()
|
public void TestCanParseMarkdownQuizWithNoQuestions()
|
||||||
@@ -199,42 +104,6 @@ b) false
|
|||||||
firstQuestion.Answers.ElementAt(1).Text.Should().Contain("endline");
|
firstQuestion.Answers.ElementAt(1).Text.Should().Contain("endline");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CanParseQuestionWithMultipleAnswers()
|
|
||||||
{
|
|
||||||
var rawMarkdownQuiz = @"
|
|
||||||
Name: Test Quiz
|
|
||||||
ShuffleAnswers: true
|
|
||||||
OneQuestionAtATime: false
|
|
||||||
DueAt: 2023-08-21T23:59:00
|
|
||||||
LockAt: 2023-08-21T23:59:00
|
|
||||||
AssignmentGroup: Assignments
|
|
||||||
AllowedAttempts: -1
|
|
||||||
Description: this is the
|
|
||||||
multi line
|
|
||||||
description
|
|
||||||
---
|
|
||||||
Which events are triggered when the user clicks on an input field?
|
|
||||||
[*] click
|
|
||||||
[*] focus
|
|
||||||
[*] mousedown
|
|
||||||
[] submit
|
|
||||||
[] change
|
|
||||||
[] mouseout
|
|
||||||
[] keydown
|
|
||||||
---
|
|
||||||
";
|
|
||||||
|
|
||||||
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
|
||||||
var firstQuestion = quiz.Questions.First();
|
|
||||||
firstQuestion.Points.Should().Be(1);
|
|
||||||
firstQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_ANSWERS);
|
|
||||||
firstQuestion.Text.Should().Contain("Which events are triggered when the user clicks on an input field?");
|
|
||||||
firstQuestion.Answers.First().Text.Should().Be("click");
|
|
||||||
firstQuestion.Answers.First().Correct.Should().BeTrue();
|
|
||||||
firstQuestion.Answers.ElementAt(3).Correct.Should().BeFalse();
|
|
||||||
firstQuestion.Answers.ElementAt(3).Text.Should().Be("submit");
|
|
||||||
}
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CanParseMultipleQuestions()
|
public void CanParseMultipleQuestions()
|
||||||
{
|
{
|
||||||
@@ -267,56 +136,7 @@ b) false
|
|||||||
secondQuestion.Points.Should().Be(2);
|
secondQuestion.Points.Should().Be(2);
|
||||||
secondQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_CHOICE);
|
secondQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_CHOICE);
|
||||||
}
|
}
|
||||||
[Test]
|
|
||||||
public void CanParseEssay()
|
|
||||||
{
|
|
||||||
var rawMarkdownQuiz = @"
|
|
||||||
Name: Test Quiz
|
|
||||||
ShuffleAnswers: true
|
|
||||||
OneQuestionAtATime: false
|
|
||||||
DueAt: 2023-08-21T23:59:00
|
|
||||||
LockAt: 2023-08-21T23:59:00
|
|
||||||
AssignmentGroup: Assignments
|
|
||||||
AllowedAttempts: -1
|
|
||||||
Description: this is the
|
|
||||||
multi line
|
|
||||||
description
|
|
||||||
---
|
|
||||||
Which events are triggered when the user clicks on an input field?
|
|
||||||
essay
|
|
||||||
";
|
|
||||||
|
|
||||||
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
|
||||||
var firstQuestion = quiz.Questions.First();
|
|
||||||
firstQuestion.Points.Should().Be(1);
|
|
||||||
firstQuestion.QuestionType.Should().Be(QuestionType.ESSAY);
|
|
||||||
firstQuestion.Text.Should().NotContain("essay");
|
|
||||||
}
|
|
||||||
[Test]
|
|
||||||
public void CanParseShortAnswer()
|
|
||||||
{
|
|
||||||
var rawMarkdownQuiz = @"
|
|
||||||
Name: Test Quiz
|
|
||||||
ShuffleAnswers: true
|
|
||||||
OneQuestionAtATime: false
|
|
||||||
DueAt: 2023-08-21T23:59:00
|
|
||||||
LockAt: 2023-08-21T23:59:00
|
|
||||||
AssignmentGroup: Assignments
|
|
||||||
AllowedAttempts: -1
|
|
||||||
Description: this is the
|
|
||||||
multi line
|
|
||||||
description
|
|
||||||
---
|
|
||||||
Which events are triggered when the user clicks on an input field?
|
|
||||||
short answer
|
|
||||||
";
|
|
||||||
|
|
||||||
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
|
||||||
var firstQuestion = quiz.Questions.First();
|
|
||||||
firstQuestion.Points.Should().Be(1);
|
|
||||||
firstQuestion.QuestionType.Should().Be(QuestionType.SHORT_ANSWER);
|
|
||||||
firstQuestion.Text.Should().NotContain("short answer");
|
|
||||||
}
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ShortAnswerToMarkdown_IsCorrect()
|
public void ShortAnswerToMarkdown_IsCorrect()
|
||||||
{
|
{
|
||||||
@@ -345,32 +165,156 @@ Which events are triggered when the user clicks on an input field?
|
|||||||
short_answer";
|
short_answer";
|
||||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void EssayQuestionToMarkdown_IsCorrect()
|
public void SerializationIsDeterministic_EmptyQuiz()
|
||||||
{
|
{
|
||||||
var rawMarkdownQuiz = @"
|
var quiz = new LocalQuiz()
|
||||||
Name: Test Quiz
|
{
|
||||||
ShuffleAnswers: true
|
Name = "Test Quiz",
|
||||||
OneQuestionAtATime: false
|
Description = "quiz description",
|
||||||
DueAt: 2023-08-21T23:59:00
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
LockAt: 2023-08-21T23:59:00
|
DueAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
AssignmentGroup: Assignments
|
ShuffleAnswers = true,
|
||||||
AllowedAttempts: -1
|
OneQuestionAtATime = true,
|
||||||
Description: this is the
|
LocalAssignmentGroupName = "Assignments"
|
||||||
multi line
|
};
|
||||||
description
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
---
|
|
||||||
Which events are triggered when the user clicks on an input field?
|
|
||||||
essay
|
|
||||||
";
|
|
||||||
|
|
||||||
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||||
var firstQuestion = quiz.Questions.First();
|
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void SerializationIsDeterministic_ShortAnswer()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "quiz description",
|
||||||
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
DueAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = true,
|
||||||
|
LocalAssignmentGroupName = "Assignments",
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Text = "test short answer",
|
||||||
|
QuestionType = QuestionType.SHORT_ANSWER,
|
||||||
|
Points = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
|
|
||||||
var questionMarkdown = firstQuestion.ToMarkdown();
|
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||||
var expectedMarkdown = @"Points: 1
|
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||||
Which events are triggered when the user clicks on an input field?
|
}
|
||||||
essay";
|
|
||||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
[Test]
|
||||||
|
public void SerializationIsDeterministic_Essay()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "quiz description",
|
||||||
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
DueAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = true,
|
||||||
|
LocalAssignmentGroupName = "Assignments",
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Text = "test essay",
|
||||||
|
QuestionType = QuestionType.ESSAY,
|
||||||
|
Points = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||||
|
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SerializationIsDeterministic_MultipleAnswer()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "quiz description",
|
||||||
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
DueAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = true,
|
||||||
|
LocalAssignmentGroupName = "Assignments",
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Text = "test multiple answer",
|
||||||
|
QuestionType = QuestionType.MULTIPLE_ANSWERS,
|
||||||
|
Points = 1,
|
||||||
|
Answers = new LocalQuizQuestionAnswer[]
|
||||||
|
{
|
||||||
|
new() {
|
||||||
|
Correct = true,
|
||||||
|
Text="yes",
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
Correct = true,
|
||||||
|
Text="no",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||||
|
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SerializationIsDeterministic_MultipleChoice()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "quiz description",
|
||||||
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
DueAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = true,
|
||||||
|
LocalAssignmentGroupName = "Assignments",
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
Text = "test multiple choice",
|
||||||
|
QuestionType = QuestionType.MULTIPLE_CHOICE,
|
||||||
|
Points = 1,
|
||||||
|
Answers = new LocalQuizQuestionAnswer[]
|
||||||
|
{
|
||||||
|
new() {
|
||||||
|
Correct = true,
|
||||||
|
Text="yes",
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
Correct = false,
|
||||||
|
Text="no",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedQuiz = LocalQuiz.ParseMarkdown(quizMarkdown);
|
||||||
|
parsedQuiz.Should().BeEquivalentTo(quiz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
244
Management.Test/Markdown/QuizQuestionMarkdownTests.cs
Normal file
244
Management.Test/Markdown/QuizQuestionMarkdownTests.cs
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
using LocalModels;
|
||||||
|
|
||||||
|
public class QuizQuestionMarkdownTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void QuzMarkdownIncludesMultipleChoiceQuestion()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "desc",
|
||||||
|
LockAt = DateTime.MaxValue,
|
||||||
|
DueAt = DateTime.MaxValue,
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = false,
|
||||||
|
LocalAssignmentGroupName = "someId",
|
||||||
|
AllowedAttempts = -1,
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new LocalQuizQuestion()
|
||||||
|
{
|
||||||
|
Id = "someid",
|
||||||
|
Points = 2,
|
||||||
|
Text = @"`some type` of question
|
||||||
|
|
||||||
|
with many
|
||||||
|
|
||||||
|
```
|
||||||
|
lines
|
||||||
|
```
|
||||||
|
",
|
||||||
|
QuestionType = QuestionType.MULTIPLE_CHOICE,
|
||||||
|
Answers = new LocalQuizQuestionAnswer[]
|
||||||
|
{
|
||||||
|
new LocalQuizQuestionAnswer() { Correct = true, Text = "true" },
|
||||||
|
new LocalQuizQuestionAnswer() { Correct = false, Text = "false" + Environment.NewLine +Environment.NewLine + "endline" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var markdown = quiz.ToMarkdown();
|
||||||
|
var expectedQuestionString = @"
|
||||||
|
Points: 2
|
||||||
|
`some type` of question
|
||||||
|
|
||||||
|
with many
|
||||||
|
|
||||||
|
```
|
||||||
|
lines
|
||||||
|
```
|
||||||
|
|
||||||
|
*a) true
|
||||||
|
b) false
|
||||||
|
|
||||||
|
endline
|
||||||
|
";
|
||||||
|
markdown.Should().Contain(expectedQuestionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void QuzMarkdownIncludesMultipleAnswerQuestion()
|
||||||
|
{
|
||||||
|
var quiz = new LocalQuiz()
|
||||||
|
{
|
||||||
|
Name = "Test Quiz",
|
||||||
|
Description = "desc",
|
||||||
|
LockAt = DateTime.MaxValue,
|
||||||
|
DueAt = DateTime.MaxValue,
|
||||||
|
ShuffleAnswers = true,
|
||||||
|
OneQuestionAtATime = false,
|
||||||
|
LocalAssignmentGroupName = "someId",
|
||||||
|
AllowedAttempts = -1,
|
||||||
|
Questions = new LocalQuizQuestion[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = "somesdid",
|
||||||
|
Text = "oneline question",
|
||||||
|
Points = 1,
|
||||||
|
QuestionType = QuestionType.MULTIPLE_ANSWERS,
|
||||||
|
Answers = new LocalQuizQuestionAnswer[]
|
||||||
|
{
|
||||||
|
new() { Correct = true, Text = "true" },
|
||||||
|
new() { Correct = true, Text = "false"},
|
||||||
|
new() { Correct = false, Text = "neither"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var markdown = quiz.ToMarkdown();
|
||||||
|
var expectedQuestionString = @"
|
||||||
|
Points: 1
|
||||||
|
oneline question
|
||||||
|
[*] true
|
||||||
|
[*] false
|
||||||
|
[ ] neither
|
||||||
|
";
|
||||||
|
markdown.Should().Contain(expectedQuestionString);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void CanParseQuestionWithMultipleAnswers()
|
||||||
|
{
|
||||||
|
var rawMarkdownQuiz = @"
|
||||||
|
Name: Test Quiz
|
||||||
|
ShuffleAnswers: true
|
||||||
|
OneQuestionAtATime: false
|
||||||
|
DueAt: 2023-08-21T23:59:00
|
||||||
|
LockAt: 2023-08-21T23:59:00
|
||||||
|
AssignmentGroup: Assignments
|
||||||
|
AllowedAttempts: -1
|
||||||
|
Description: this is the
|
||||||
|
multi line
|
||||||
|
description
|
||||||
|
---
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
[*] click
|
||||||
|
[*] focus
|
||||||
|
[*] mousedown
|
||||||
|
[] submit
|
||||||
|
[] change
|
||||||
|
[] mouseout
|
||||||
|
[] keydown
|
||||||
|
---
|
||||||
|
";
|
||||||
|
|
||||||
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
|
var firstQuestion = quiz.Questions.First();
|
||||||
|
firstQuestion.Points.Should().Be(1);
|
||||||
|
firstQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_ANSWERS);
|
||||||
|
firstQuestion.Text.Should().Contain("Which events are triggered when the user clicks on an input field?");
|
||||||
|
firstQuestion.Answers.First().Text.Should().Be("click");
|
||||||
|
firstQuestion.Answers.First().Correct.Should().BeTrue();
|
||||||
|
firstQuestion.Answers.ElementAt(3).Correct.Should().BeFalse();
|
||||||
|
firstQuestion.Answers.ElementAt(3).Text.Should().Be("submit");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CanParseEssay()
|
||||||
|
{
|
||||||
|
var rawMarkdownQuiz = @"
|
||||||
|
Name: Test Quiz
|
||||||
|
ShuffleAnswers: true
|
||||||
|
OneQuestionAtATime: false
|
||||||
|
DueAt: 2023-08-21T23:59:00
|
||||||
|
LockAt: 2023-08-21T23:59:00
|
||||||
|
AssignmentGroup: Assignments
|
||||||
|
AllowedAttempts: -1
|
||||||
|
Description: this is the
|
||||||
|
multi line
|
||||||
|
description
|
||||||
|
---
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
essay
|
||||||
|
";
|
||||||
|
|
||||||
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
|
var firstQuestion = quiz.Questions.First();
|
||||||
|
firstQuestion.Points.Should().Be(1);
|
||||||
|
firstQuestion.QuestionType.Should().Be(QuestionType.ESSAY);
|
||||||
|
firstQuestion.Text.Should().NotContain("essay");
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void CanParseShortAnswer()
|
||||||
|
{
|
||||||
|
var rawMarkdownQuiz = @"
|
||||||
|
Name: Test Quiz
|
||||||
|
ShuffleAnswers: true
|
||||||
|
OneQuestionAtATime: false
|
||||||
|
DueAt: 2023-08-21T23:59:00
|
||||||
|
LockAt: 2023-08-21T23:59:00
|
||||||
|
AssignmentGroup: Assignments
|
||||||
|
AllowedAttempts: -1
|
||||||
|
Description: this is the
|
||||||
|
multi line
|
||||||
|
description
|
||||||
|
---
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
short answer
|
||||||
|
";
|
||||||
|
|
||||||
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
|
var firstQuestion = quiz.Questions.First();
|
||||||
|
firstQuestion.Points.Should().Be(1);
|
||||||
|
firstQuestion.QuestionType.Should().Be(QuestionType.SHORT_ANSWER);
|
||||||
|
firstQuestion.Text.Should().NotContain("short answer");
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void ShortAnswerToMarkdown_IsCorrect()
|
||||||
|
{
|
||||||
|
var rawMarkdownQuiz = @"
|
||||||
|
Name: Test Quiz
|
||||||
|
ShuffleAnswers: true
|
||||||
|
OneQuestionAtATime: false
|
||||||
|
DueAt: 2023-08-21T23:59:00
|
||||||
|
LockAt: 2023-08-21T23:59:00
|
||||||
|
AssignmentGroup: Assignments
|
||||||
|
AllowedAttempts: -1
|
||||||
|
Description: this is the
|
||||||
|
multi line
|
||||||
|
description
|
||||||
|
---
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
short answer
|
||||||
|
";
|
||||||
|
|
||||||
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
|
var firstQuestion = quiz.Questions.First();
|
||||||
|
|
||||||
|
var questionMarkdown = firstQuestion.ToMarkdown();
|
||||||
|
var expectedMarkdown = @"Points: 1
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
short_answer";
|
||||||
|
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void EssayQuestionToMarkdown_IsCorrect()
|
||||||
|
{
|
||||||
|
var rawMarkdownQuiz = @"
|
||||||
|
Name: Test Quiz
|
||||||
|
ShuffleAnswers: true
|
||||||
|
OneQuestionAtATime: false
|
||||||
|
DueAt: 2023-08-21T23:59:00
|
||||||
|
LockAt: 2023-08-21T23:59:00
|
||||||
|
AssignmentGroup: Assignments
|
||||||
|
AllowedAttempts: -1
|
||||||
|
Description: this is the
|
||||||
|
multi line
|
||||||
|
description
|
||||||
|
---
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
essay
|
||||||
|
";
|
||||||
|
|
||||||
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
|
var firstQuestion = quiz.Questions.First();
|
||||||
|
|
||||||
|
var questionMarkdown = firstQuestion.ToMarkdown();
|
||||||
|
var expectedMarkdown = @"Points: 1
|
||||||
|
Which events are triggered when the user clicks on an input field?
|
||||||
|
essay";
|
||||||
|
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
@using Management.Web.Shared.Module.Assignment
|
@using Management.Web.Shared.Module.Assignment
|
||||||
@using Management.Web.Shared.Components
|
@using Management.Web.Shared.Components
|
||||||
|
|
||||||
@inject YamlManager yamlManager
|
@inject FileStorageManager fileStorageManager
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@inject AssignmentEditorContext assignmentContext
|
@inject AssignmentEditorContext assignmentContext
|
||||||
@@ -23,28 +23,28 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string? AssignmentId { get; set; } = default!;
|
public string? AssignmentId { get; set; } = default!;
|
||||||
|
|
||||||
private bool loading { get; set; }= true;
|
private bool loading { get; set; } = true;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if(loading)
|
if (loading)
|
||||||
{
|
{
|
||||||
loading = false;
|
loading = false;
|
||||||
logger.LogInformation($"loading assignment {CourseName} {AssignmentId}");
|
logger.LogInformation($"loading assignment {CourseName} {AssignmentId}");
|
||||||
if(planner.LocalCourse == null)
|
if (planner.LocalCourse == null)
|
||||||
{
|
{
|
||||||
var courses = await yamlManager.LoadSavedCourses();
|
var courses = await fileStorageManager.LoadSavedCourses();
|
||||||
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
||||||
logger.LogInformation($"set course to '{planner.LocalCourse?.Settings.Name}'");
|
logger.LogInformation($"set course to '{planner.LocalCourse?.Settings.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(assignmentContext.Assignment == null)
|
if (assignmentContext.Assignment == null)
|
||||||
{
|
{
|
||||||
var assignment = planner
|
var assignment = planner
|
||||||
.LocalCourse?
|
.LocalCourse?
|
||||||
.Modules
|
.Modules
|
||||||
.SelectMany(m => m.Assignments)
|
.SelectMany(m => m.Assignments)
|
||||||
.FirstOrDefault(a => a.Id == AssignmentId);
|
.FirstOrDefault(a => a.Id == AssignmentId);
|
||||||
|
|
||||||
assignmentContext.Assignment = assignment;
|
assignmentContext.Assignment = assignment;
|
||||||
logger.LogInformation($"set assignment to '{assignmentContext.Assignment?.Name}'");
|
logger.LogInformation($"set assignment to '{assignmentContext.Assignment?.Name}'");
|
||||||
@@ -56,12 +56,12 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(loading)
|
@if (loading)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(planner.LocalCourse != null && assignmentContext.Assignment != null)
|
@if (planner.LocalCourse != null && assignmentContext.Assignment != null)
|
||||||
{
|
{
|
||||||
<AssignmentForm />
|
<AssignmentForm />
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
@using Management.Web.Shared.Module.Assignment
|
@using Management.Web.Shared.Module.Assignment
|
||||||
@using Management.Web.Shared.Components
|
@using Management.Web.Shared.Components
|
||||||
|
|
||||||
@inject YamlManager yamlManager
|
@inject FileStorageManager fileStorageManager
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@inject NavigationManager navigtion
|
@inject NavigationManager navigtion
|
||||||
@@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if(planner.LocalCourse == null)
|
if (planner.LocalCourse == null)
|
||||||
{
|
{
|
||||||
var courses = await yamlManager.LoadSavedCourses();
|
var courses = await fileStorageManager.LoadSavedCourses();
|
||||||
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
||||||
}
|
}
|
||||||
base.OnInitialized();
|
base.OnInitialized();
|
||||||
@@ -39,43 +39,34 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(loading)
|
@if (loading)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(planner.LocalCourse != null)
|
@if (planner.LocalCourse != null)
|
||||||
{
|
{
|
||||||
<div class="mb-3 d-flex justify-content-between" style="height: 4em;">
|
<div class="mb-3 d-flex justify-content-between" style="height: 4em;">
|
||||||
<div class="my-auto">
|
<div class="my-auto">
|
||||||
<button
|
<button @onclick="selectNewCourse" class="btn btn-primary">
|
||||||
@onclick="selectNewCourse"
|
Select New Course
|
||||||
class="btn btn-primary"
|
</button>
|
||||||
>
|
<CourseSettings />
|
||||||
Select New Course
|
<AssignmentTemplateManagement />
|
||||||
</button>
|
|
||||||
<CourseSettings />
|
|
||||||
<AssignmentTemplateManagement />
|
|
||||||
|
|
||||||
<button
|
<button class="btn btn-outline-primary" @onclick="planner.SyncWithCanvas">
|
||||||
class="btn btn-outline-primary"
|
Sync With Canvas
|
||||||
@onclick="planner.SyncWithCanvas"
|
</button>
|
||||||
>
|
<a class="btn btn-outline-secondary" target="_blank"
|
||||||
Sync With Canvas
|
href="@($"{Environment.GetEnvironmentVariable("CANVAS_URL")}/courses/{planner.LocalCourse.Settings.CanvasId}")">
|
||||||
</button>
|
View In Canvas
|
||||||
<a
|
</a>
|
||||||
class="btn btn-outline-secondary"
|
<div class="my-auto ms-2 d-inline">
|
||||||
target="_blank"
|
@planner.LocalCourse.Settings.Name
|
||||||
href="@($"{Environment.GetEnvironmentVariable("CANVAS_URL")}/courses/{planner.LocalCourse.Settings.CanvasId}")"
|
|
||||||
>
|
|
||||||
View In Canvas
|
|
||||||
</a>
|
|
||||||
<div class="my-auto ms-2 d-inline">
|
|
||||||
@planner.LocalCourse.Settings.Name
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if(planner.LoadingCanvasData)
|
@if (planner.LoadingCanvasData)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
@using Management.Web.Shared.Components
|
@using Management.Web.Shared.Components
|
||||||
@using Management.Web.Shared.Components.Quiz.Markdown
|
@using Management.Web.Shared.Components.Quiz.Markdown
|
||||||
|
|
||||||
@inject YamlManager yamlManager
|
@inject FileStorageManager fileStorageManager
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@inject QuizEditorContext quizContext
|
@inject QuizEditorContext quizContext
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string? QuizName { get; set; } = default!;
|
public string? QuizName { get; set; } = default!;
|
||||||
|
|
||||||
private bool loading { get; set; }= true;
|
private bool loading { get; set; } = true;
|
||||||
private bool addingQuizToCanvas = false;
|
private bool addingQuizToCanvas = false;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
quizContext.StateHasChanged += reload;
|
quizContext.StateHasChanged += reload;
|
||||||
@@ -43,31 +43,31 @@
|
|||||||
}
|
}
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if(loading)
|
if (loading)
|
||||||
{
|
{
|
||||||
loading = false;
|
loading = false;
|
||||||
logger.LogInformation($"loading quiz {CourseName} {QuizName}");
|
logger.LogInformation($"loading quiz {CourseName} {QuizName}");
|
||||||
if(planner.LocalCourse == null)
|
if (planner.LocalCourse == null)
|
||||||
{
|
{
|
||||||
var courses = await yamlManager.LoadSavedCourses();
|
var courses = await fileStorageManager.LoadSavedCourses();
|
||||||
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
planner.LocalCourse = courses.First(c => c.Settings.Name == CourseName);
|
||||||
logger.LogInformation($"set course to '{planner.LocalCourse?.Settings.Name}'");
|
logger.LogInformation($"set course to '{planner.LocalCourse?.Settings.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(quizContext.Quiz == null)
|
if (quizContext.Quiz == null)
|
||||||
{
|
{
|
||||||
var quiz = planner
|
var quiz = planner
|
||||||
.LocalCourse?
|
.LocalCourse?
|
||||||
.Modules
|
.Modules
|
||||||
.SelectMany(m => m.Quizzes)
|
.SelectMany(m => m.Quizzes)
|
||||||
.FirstOrDefault(q => q.Name == QuizName);
|
.FirstOrDefault(q => q.Name == QuizName);
|
||||||
|
|
||||||
quizContext.Quiz = quiz;
|
quizContext.Quiz = quiz;
|
||||||
logger.LogInformation($"set quiz to '{quizContext.Quiz?.Name}'");
|
logger.LogInformation($"set quiz to '{quizContext.Quiz?.Name}'");
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
if(planner.CanvasQuizzes == null)
|
if (planner.CanvasQuizzes == null)
|
||||||
{
|
{
|
||||||
await planner.LoadCanvasData();
|
await planner.LoadCanvasData();
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,8 @@
|
|||||||
|
|
||||||
private CanvasQuiz? quizInCanvas => planner.CanvasQuizzes?.FirstOrDefault(q => q.Title == quizContext.Quiz?.Name);
|
private CanvasQuiz? quizInCanvas => planner.CanvasQuizzes?.FirstOrDefault(q => q.Title == quizContext.Quiz?.Name);
|
||||||
|
|
||||||
private string canvasQuizUrl => $"https://snow.instructure.com/courses/{planner.LocalCourse?.Settings.CanvasId}/quizzes/{quizInCanvas?.Id}";
|
private string canvasQuizUrl =>
|
||||||
|
$"https://snow.instructure.com/courses/{planner.LocalCourse?.Settings.CanvasId}/quizzes/{quizInCanvas?.Id}";
|
||||||
|
|
||||||
private int? quizPoints => quizContext.Quiz?.Questions.Sum(q => q.Points);
|
private int? quizPoints => quizContext.Quiz?.Questions.Sum(q => q.Points);
|
||||||
}
|
}
|
||||||
@@ -108,10 +109,7 @@
|
|||||||
<section>
|
<section>
|
||||||
<div class="row justify-content-between">
|
<div class="row justify-content-between">
|
||||||
<div class="col-auto my-auto">
|
<div class="col-auto my-auto">
|
||||||
<button
|
<button class="btn btn-outline-secondary" @onclick="done">
|
||||||
class="btn btn-outline-secondary"
|
|
||||||
@onclick="done"
|
|
||||||
>
|
|
||||||
← go back
|
← go back
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,7 +119,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if(quizContext.Quiz == null)
|
@if (quizContext.Quiz == null)
|
||||||
{
|
{
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
@@ -131,9 +129,9 @@
|
|||||||
<h3>
|
<h3>
|
||||||
Points: @quizPoints
|
Points: @quizPoints
|
||||||
</h3>
|
</h3>
|
||||||
@if(quizInCanvas != null)
|
@if (quizInCanvas != null)
|
||||||
{
|
{
|
||||||
@if(quizInCanvas?.Published == true)
|
@if (quizInCanvas?.Published == true)
|
||||||
{
|
{
|
||||||
<div class="text-success">
|
<div class="text-success">
|
||||||
Published!
|
Published!
|
||||||
@@ -150,12 +148,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
class="flex-grow-1 w-100 d-flex justify-content-center overflow-y-auto overflow-x-hidden border rounded-4 bg-dark-subtle py-3 px-1"
|
class="flex-grow-1 w-100 d-flex justify-content-center overflow-y-auto overflow-x-hidden border rounded-4 bg-dark-subtle py-3 px-1"
|
||||||
style="min-height: 10%;max-width: 100%;"
|
style="min-height: 10%;max-width: 100%;">
|
||||||
>
|
|
||||||
<div class="w-100" style="max-width: 120em; max-height: 100%;">
|
<div class="w-100" style="max-width: 120em; max-height: 100%;">
|
||||||
@if(quizContext.Quiz != null)
|
@if (quizContext.Quiz != null)
|
||||||
{
|
{
|
||||||
<MarkdownQuizForm />
|
<MarkdownQuizForm />
|
||||||
}
|
}
|
||||||
@@ -164,45 +161,29 @@
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<section>
|
<section>
|
||||||
@if(quizContext.Quiz != null)
|
@if (quizContext.Quiz != null)
|
||||||
{
|
{
|
||||||
<div class="row justify-content-end">
|
<div class="row justify-content-end">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<ConfirmationModal
|
<ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirm="deleteQuiz"
|
||||||
Label="Delete"
|
Disabled="@addingQuizToCanvas" />
|
||||||
Class="btn btn-danger"
|
<button class="btn btn-outline-secondary me-1" @onclick="addToCanvas" disabled="@addingQuizToCanvas">
|
||||||
OnConfirm="deleteQuiz"
|
|
||||||
Disabled="@addingQuizToCanvas"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-secondary me-1"
|
|
||||||
@onclick="addToCanvas"
|
|
||||||
disabled="@addingQuizToCanvas"
|
|
||||||
>
|
|
||||||
Add to Canvas
|
Add to Canvas
|
||||||
</button>
|
</button>
|
||||||
@if(quizInCanvas != null)
|
@if (quizInCanvas != null)
|
||||||
{
|
{
|
||||||
<a
|
<a class="btn btn-outline-secondary me-1" href="@canvasQuizUrl" target="_blank">
|
||||||
class="btn btn-outline-secondary me-1"
|
|
||||||
href="@canvasQuizUrl"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
View in Canvas
|
View in Canvas
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
<button
|
<button class="btn btn-primary" @onclick="done" disabled="@addingQuizToCanvas">
|
||||||
class="btn btn-primary"
|
|
||||||
@onclick="done"
|
|
||||||
disabled="@addingQuizToCanvas"
|
|
||||||
>
|
|
||||||
Done
|
Done
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(addingQuizToCanvas)
|
@if (addingQuizToCanvas)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ global using LocalModels;
|
|||||||
global using Management.Planner;
|
global using Management.Planner;
|
||||||
global using Management.Web.Shared.Components;
|
global using Management.Web.Shared.Components;
|
||||||
global using Management.Web.Shared;
|
global using Management.Web.Shared;
|
||||||
|
global using Management.Web.Shared.Components.Forms;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
@@ -44,7 +45,7 @@ builder.Services.AddScoped<CanvasQuizService>();
|
|||||||
builder.Services.AddScoped<CanvasModuleService>();
|
builder.Services.AddScoped<CanvasModuleService>();
|
||||||
builder.Services.AddScoped<CanvasService, CanvasService>();
|
builder.Services.AddScoped<CanvasService, CanvasService>();
|
||||||
|
|
||||||
builder.Services.AddScoped<YamlManager>();
|
builder.Services.AddScoped<FileStorageManager>();
|
||||||
builder.Services.AddScoped<CoursePlanner>();
|
builder.Services.AddScoped<CoursePlanner>();
|
||||||
builder.Services.AddScoped<AssignmentEditorContext>();
|
builder.Services.AddScoped<AssignmentEditorContext>();
|
||||||
builder.Services.AddScoped<QuizEditorContext>();
|
builder.Services.AddScoped<QuizEditorContext>();
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
@using Management.Web.Shared.Components
|
|
||||||
|
|
||||||
@inject QuizEditorContext quizContext
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private Modal? modal { get; set; }
|
|
||||||
private string name { get; set; } = "";
|
|
||||||
private string description { get; set; } = "";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
quizContext.StateHasChanged += reload;
|
|
||||||
}
|
|
||||||
private void reload()
|
|
||||||
{
|
|
||||||
if (quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
name = quizContext.Quiz.Name;
|
|
||||||
description = quizContext.Quiz.Description;
|
|
||||||
|
|
||||||
modal?.Show();
|
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
quizContext.StateHasChanged -= reload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteQuiz()
|
|
||||||
{
|
|
||||||
quizContext.DeleteQuiz();
|
|
||||||
modal?.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addQuestion()
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newQuestion = new LocalQuizQuestion
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Points = 1,
|
|
||||||
};
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
Questions = quizContext.Quiz.Questions.Append(newQuestion).ToArray()
|
|
||||||
};
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeQuestion()
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newQuestion = new LocalQuizQuestion();
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
Questions = quizContext.Quiz.Questions.Take(quizContext.Quiz.Questions.Count() - 1)
|
|
||||||
};
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateQuestion(LocalQuizQuestion updatedQuestion)
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newQuestions = quizContext.Quiz.Questions.Select(q =>
|
|
||||||
q.Id == updatedQuestion.Id
|
|
||||||
? updatedQuestion
|
|
||||||
: q
|
|
||||||
);
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
Questions = newQuestions,
|
|
||||||
};
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNewName(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
Name = e.Value?.ToString() ?? ""
|
|
||||||
};
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void handleNewDescription(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
Description = e.Value?.ToString() ?? ""
|
|
||||||
};
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task addToCanvas()
|
|
||||||
{
|
|
||||||
await quizContext.AddQuizToCanvas();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<Modal @ref="modal" OnHide="() => quizContext.Quiz = null" >
|
|
||||||
<Title>
|
|
||||||
<div class="row justify-content-between">
|
|
||||||
<div class="col-auto">
|
|
||||||
@quizContext.Quiz?.Name
|
|
||||||
</div>
|
|
||||||
<div class="col-auto me-3">
|
|
||||||
Points: @quizContext.Quiz?.Questions.Sum(q => q.Points)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Title>
|
|
||||||
<Body>
|
|
||||||
@if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
<div class="m-1">
|
|
||||||
<label class="form-label">
|
|
||||||
Name
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
class="form-control"
|
|
||||||
@bind="name"
|
|
||||||
@oninput="handleNewName"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="m-1">
|
|
||||||
<label class="form-label">
|
|
||||||
Description
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
class="form-control"
|
|
||||||
@bind="description"
|
|
||||||
@oninput="handleNewDescription"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<QuizSettings />
|
|
||||||
|
|
||||||
@foreach(var (question, i) in quizContext.Quiz.Questions.Select((q, i) => (q, i)))
|
|
||||||
{
|
|
||||||
<QuizQuestionForm
|
|
||||||
@key="@question.Id"
|
|
||||||
Index="i"
|
|
||||||
Question="question"
|
|
||||||
UpdateQuestion="updateQuestion"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-danger"
|
|
||||||
@onclick="removeQuestion"
|
|
||||||
>
|
|
||||||
- question
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-primary"
|
|
||||||
@onclick="addQuestion"
|
|
||||||
>
|
|
||||||
+ question
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</Body>
|
|
||||||
<Footer>
|
|
||||||
<ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirm="deleteQuiz" />
|
|
||||||
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-secondary"
|
|
||||||
@onclick="addToCanvas"
|
|
||||||
>
|
|
||||||
Add to Canvas
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary"
|
|
||||||
@onclick="() => modal?.Hide()"
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</button>
|
|
||||||
</Footer>
|
|
||||||
</Modal>
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
@inject QuizEditorContext quizContext
|
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter, EditorRequired]
|
|
||||||
public LocalQuizQuestion Question { get; set; } = default!;
|
|
||||||
[Parameter, EditorRequired]
|
|
||||||
public int Index { get; set; } = default!;
|
|
||||||
[Parameter, EditorRequired]
|
|
||||||
public Action<LocalQuizQuestion> UpdateQuestion { get; set; } = (_) => {};
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
if(questionType == string.Empty)
|
|
||||||
questionType = Question.QuestionType;
|
|
||||||
if(text == string.Empty)
|
|
||||||
text = Question.Text;
|
|
||||||
|
|
||||||
if(answers.Count() == 0)
|
|
||||||
answers = Question.Answers;
|
|
||||||
if (points == 0)
|
|
||||||
points = Question.Points;
|
|
||||||
|
|
||||||
base.OnParametersSet();
|
|
||||||
}
|
|
||||||
private string text { get; set; } = string.Empty;
|
|
||||||
private string questionType { get; set; } = string.Empty;
|
|
||||||
private int points { get; set; } = 1;
|
|
||||||
private IEnumerable<LocalQuizQuestionAnswer> answers { get; set; } = Enumerable.Empty<LocalQuizQuestionAnswer>();
|
|
||||||
|
|
||||||
private void handleTypeUpdate(string type)
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
questionType = type;
|
|
||||||
var newQuestion = Question with
|
|
||||||
{
|
|
||||||
QuestionType = questionType
|
|
||||||
};
|
|
||||||
|
|
||||||
UpdateQuestion(newQuestion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void handlePointsInput(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
if (quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var pointsString = e.Value?.ToString() ?? "0";
|
|
||||||
|
|
||||||
var newPoints = int.Parse(pointsString == string.Empty ? "0" : pointsString);
|
|
||||||
var newQuestion = Question with
|
|
||||||
{
|
|
||||||
Points = newPoints
|
|
||||||
};
|
|
||||||
UpdateQuestion(newQuestion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAnswer()
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
var newAnswer = new LocalQuizQuestionAnswer();
|
|
||||||
|
|
||||||
answers = answers.Append(newAnswer);
|
|
||||||
UpdateQuestion(Question with { Answers = answers });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeAnswer()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
answers = answers.Take(Question.Answers.Count() - 1);
|
|
||||||
UpdateQuestion(Question with { Answers = answers });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveAnswer(LocalQuizQuestionAnswer newAnswer, int index)
|
|
||||||
{
|
|
||||||
if(questionType == QuestionType.MULTIPLE_CHOICE && newAnswer.Correct)
|
|
||||||
{
|
|
||||||
answers = answers.Select((a, i) =>
|
|
||||||
index == i
|
|
||||||
? newAnswer
|
|
||||||
: a with { Correct = false }
|
|
||||||
).ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
answers = answers.Select((a, i) =>
|
|
||||||
index == i
|
|
||||||
? newAnswer
|
|
||||||
: a
|
|
||||||
).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateQuestion(Question with { Answers = answers });
|
|
||||||
}
|
|
||||||
private void handleTextUpdate(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
var newText = e.Value?.ToString() ?? "";
|
|
||||||
UpdateQuestion(Question with { Text = newText });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="my-1 p-2 border border-3 rounded">
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<label
|
|
||||||
for="question_text"
|
|
||||||
class="form-label"
|
|
||||||
>
|
|
||||||
Question Text
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
class="form-control"
|
|
||||||
id="question_text"
|
|
||||||
name="question_text"
|
|
||||||
@bind="text"
|
|
||||||
@oninput="handleTextUpdate"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@foreach (var typeOption in QuestionType.AllTypes)
|
|
||||||
{
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="@(Question.Id + "question_type")"
|
|
||||||
id="@(Question.Id + typeOption)" value="@typeOption" checked="@(typeOption == questionType)"
|
|
||||||
@onchange="() => handleTypeUpdate(typeOption)">
|
|
||||||
<label class="form-check-label" for="@(Question.Id + typeOption)">
|
|
||||||
@typeOption
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="mb-3 row">
|
|
||||||
<div class="col-auto">
|
|
||||||
<label
|
|
||||||
for="exampleInputEmail1"
|
|
||||||
class="form-label"
|
|
||||||
>
|
|
||||||
Points
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
class="form-control"
|
|
||||||
id="exampleInputEmail1"
|
|
||||||
@bind="points"
|
|
||||||
@oninput="handlePointsInput"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>Answers:</div>
|
|
||||||
|
|
||||||
@if(questionType == QuestionType.MULTIPLE_ANSWERS || questionType == QuestionType.MULTIPLE_CHOICE)
|
|
||||||
{
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-danger"
|
|
||||||
@onclick="removeAnswer"
|
|
||||||
>
|
|
||||||
- Remove Answer
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-primary"
|
|
||||||
@onclick="addAnswer"
|
|
||||||
>
|
|
||||||
+ Add Answer
|
|
||||||
</button>
|
|
||||||
|
|
||||||
@foreach(var (answer, i) in answers.Select((a, i) => (a, i)))
|
|
||||||
{
|
|
||||||
<EditableQuizAnswer
|
|
||||||
Answer="answer"
|
|
||||||
AnswerIndex="i"
|
|
||||||
QuestionIndex="Index"
|
|
||||||
SaveAnswer="saveAnswer"
|
|
||||||
Question="Question"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
@using Management.Web.Shared.Components
|
|
||||||
@using Management.Web.Shared.Components.Forms
|
|
||||||
|
|
||||||
@inject QuizEditorContext quizContext
|
|
||||||
@inject CoursePlanner planner
|
|
||||||
|
|
||||||
@code {
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
quizContext.StateHasChanged += reload;
|
|
||||||
}
|
|
||||||
private void reload()
|
|
||||||
{
|
|
||||||
if (quizContext.Quiz != null)
|
|
||||||
{
|
|
||||||
if (lockAt == null)
|
|
||||||
lockAt = quizContext.Quiz.LockAt;
|
|
||||||
if (!shuffleAnswers)
|
|
||||||
shuffleAnswers = quizContext.Quiz.ShuffleAnswers;
|
|
||||||
if (!oneQuestionAtATime)
|
|
||||||
oneQuestionAtATime = quizContext.Quiz.OneQuestionAtATime;
|
|
||||||
if (allowedAttempts == 0)
|
|
||||||
allowedAttempts = quizContext.Quiz.AllowedAttempts;
|
|
||||||
|
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
quizContext.StateHasChanged -= reload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DateTime? lockAt { get; set; }
|
|
||||||
private bool shuffleAnswers { get; set; }
|
|
||||||
private bool oneQuestionAtATime { get; set; }
|
|
||||||
private int allowedAttempts { get; set; }
|
|
||||||
|
|
||||||
private void setAssignmentGroup(LocalAssignmentGroup? group)
|
|
||||||
{
|
|
||||||
if(quizContext.Quiz == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var newQuiz = quizContext.Quiz with
|
|
||||||
{
|
|
||||||
LocalAssignmentGroupName = group?.Name
|
|
||||||
};
|
|
||||||
|
|
||||||
quizContext.SaveQuiz(newQuiz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalAssignmentGroup? selectedAssignmentGroup =>
|
|
||||||
planner
|
|
||||||
.LocalCourse?
|
|
||||||
.Settings
|
|
||||||
.AssignmentGroups
|
|
||||||
.FirstOrDefault(g => g.Name == quizContext.Quiz?.LocalAssignmentGroupName);
|
|
||||||
}
|
|
||||||
@if(planner.LocalCourse != null )
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<ButtonSelect
|
|
||||||
Label="Assignment Group"
|
|
||||||
Options="planner.LocalCourse.Settings.AssignmentGroups"
|
|
||||||
GetName="(g) => g?.Name"
|
|
||||||
OnSelect="(g) => setAssignmentGroup(g)"
|
|
||||||
SelectedOption="selectedAssignmentGroup"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
@using LocalModels
|
@using LocalModels
|
||||||
|
|
||||||
@inject YamlManager yamlManager
|
@inject FileStorageManager fileStorageManager
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject ILogger<CurrentFiles> logger
|
@inject ILogger<CurrentFiles> logger
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
public IEnumerable<LocalCourse>? localCourses { get; set; }
|
public IEnumerable<LocalCourse>? localCourses { get; set; }
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
localCourses = await yamlManager.LoadSavedCourses();
|
localCourses = await fileStorageManager.LoadSavedCourses();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleClick(MouseEventArgs e, LocalCourse course)
|
void handleClick(MouseEventArgs e, LocalCourse course)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
@using LocalModels
|
@using LocalModels
|
||||||
|
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
@inject YamlManager yamlManager
|
@inject FileStorageManager fileStorageManager
|
||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@@ -15,18 +15,18 @@
|
|||||||
private bool loadingTerms = false;
|
private bool loadingTerms = false;
|
||||||
private bool loadingCourses = false;
|
private bool loadingCourses = false;
|
||||||
public IEnumerable<LocalCourse>? localCourses { get; set; }
|
public IEnumerable<LocalCourse>? localCourses { get; set; }
|
||||||
private IEnumerable<EnrollmentTermModel>? terms { get; set; } = null;
|
private IEnumerable<EnrollmentTermModel>? terms { get; set; } = null;
|
||||||
private IEnumerable<CourseModel>? courses { get; set;} = null;
|
private IEnumerable<CourseModel>? courses { get; set; } = null;
|
||||||
private ulong? _selectedTermId { get; set; }
|
private ulong? _selectedTermId { get; set; }
|
||||||
private ulong? selectedTermId
|
private ulong? selectedTermId
|
||||||
{
|
{
|
||||||
get => _selectedTermId;
|
get => _selectedTermId;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_selectedTermId = value;
|
_selectedTermId = value;
|
||||||
this.InvokeAsync(updateCourses);
|
this.InvokeAsync(updateCourses);
|
||||||
@* updateCourses(); *@
|
@* updateCourses(); *@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private EnrollmentTermModel? selectedTerm
|
private EnrollmentTermModel? selectedTerm
|
||||||
{
|
{
|
||||||
@@ -34,16 +34,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ulong? _selectedCourseId { get; set; }
|
private ulong? _selectedCourseId { get; set; }
|
||||||
private ulong? selectedCourseId
|
private ulong? selectedCourseId
|
||||||
{
|
{
|
||||||
get => _selectedCourseId;
|
get => _selectedCourseId;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_selectedCourseId = value;
|
_selectedCourseId = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CourseModel? selectedCourse
|
private CourseModel? selectedCourse
|
||||||
{
|
{
|
||||||
get => courses?.First(c => c.Id == selectedCourseId);
|
get => courses?.First(c => c.Id == selectedCourseId);
|
||||||
}
|
}
|
||||||
@@ -56,32 +56,33 @@
|
|||||||
}
|
}
|
||||||
private async Task YamlTrigger()
|
private async Task YamlTrigger()
|
||||||
{
|
{
|
||||||
if(selectedCourse != null)
|
if (selectedCourse != null)
|
||||||
{
|
{
|
||||||
var course = new LocalCourse
|
var course = new LocalCourse
|
||||||
{
|
{
|
||||||
Modules = new LocalModule[] {},
|
Modules = new LocalModule[] { },
|
||||||
Settings = new LocalCourseSettings() {
|
Settings = new LocalCourseSettings()
|
||||||
Name = selectedCourse.Name,
|
{
|
||||||
CanvasId = selectedCourse.Id,
|
Name = selectedCourse.Name,
|
||||||
StartDate = selectedTerm?.StartAt ?? new DateTime(),
|
CanvasId = selectedCourse.Id,
|
||||||
EndDate = selectedTerm?.EndAt ?? new DateTime(),
|
StartDate = selectedTerm?.StartAt ?? new DateTime(),
|
||||||
DaysOfWeek = days,
|
EndDate = selectedTerm?.EndAt ?? new DateTime(),
|
||||||
}
|
DaysOfWeek = days,
|
||||||
};
|
}
|
||||||
await yamlManager.SaveCourseAsync(course);
|
};
|
||||||
|
await fileStorageManager.SaveCourseAsync(course);
|
||||||
NewFileCreated();
|
NewFileCreated();
|
||||||
}
|
}
|
||||||
await updateCourses();
|
await updateCourses();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task updateCourses()
|
private async Task updateCourses()
|
||||||
{
|
{
|
||||||
if(selectedTermId != null)
|
if (selectedTermId != null)
|
||||||
{
|
{
|
||||||
loadingCourses = true;
|
loadingCourses = true;
|
||||||
|
|
||||||
localCourses = await yamlManager.LoadSavedCourses();
|
localCourses = await fileStorageManager.LoadSavedCourses();
|
||||||
var storedCourseIds = localCourses.Select(c => c.Settings.CanvasId);
|
var storedCourseIds = localCourses.Select(c => c.Settings.CanvasId);
|
||||||
var allCourses = await canvas.GetCourses((ulong)selectedTermId);
|
var allCourses = await canvas.GetCourses((ulong)selectedTermId);
|
||||||
courses = allCourses.Where(c => !storedCourseIds.Contains(c.Id));
|
courses = allCourses.Where(c => !storedCourseIds.Contains(c.Id));
|
||||||
@@ -94,7 +95,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(loadingTerms)
|
@if (loadingTerms)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
@@ -102,13 +103,13 @@
|
|||||||
@if (terms != null)
|
@if (terms != null)
|
||||||
{
|
{
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<label for="termselect">Select Term:</label>
|
<label for="termselect">Select Term:</label>
|
||||||
<select id="termselect" class="form-select" @bind="selectedTermId">
|
<select id="termselect" class="form-select" @bind="selectedTermId">
|
||||||
@foreach (var term in terms)
|
@foreach (var term in terms)
|
||||||
{
|
{
|
||||||
<option value="@term.Id">@term.Name</option>
|
<option value="@term.Id">@term.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,18 +118,18 @@
|
|||||||
|
|
||||||
@if (selectedTerm is not null)
|
@if (selectedTerm is not null)
|
||||||
{
|
{
|
||||||
@if(loadingCourses)
|
@if (loadingCourses)
|
||||||
{
|
{
|
||||||
<Spinner />
|
<Spinner />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(courses != null)
|
@if (courses != null)
|
||||||
{
|
{
|
||||||
<div class="row justify-content-center m-3">
|
<div class="row justify-content-center m-3">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<label for="courseselect">Select Course:</label>
|
<label for="courseselect">Select Course:</label>
|
||||||
<select id="courseselect" class="form-select" @bind="selectedCourseId">
|
<select id="courseselect" class="form-select" @bind="selectedCourseId">
|
||||||
@foreach (var course in courses)
|
@foreach (var course in courses)
|
||||||
{
|
{
|
||||||
<option value="@course.Id">@course.Name</option>
|
<option value="@course.Id">@course.Name</option>
|
||||||
}
|
}
|
||||||
@@ -140,9 +141,9 @@
|
|||||||
<h5 class="text-center mt-3">Select Days Of Week</h5>
|
<h5 class="text-center mt-3">Select Days Of Week</h5>
|
||||||
<div class="row m-3">
|
<div class="row m-3">
|
||||||
@foreach (DayOfWeek day in (DayOfWeek[])Enum.GetValues(typeof(DayOfWeek)))
|
@foreach (DayOfWeek day in (DayOfWeek[])Enum.GetValues(typeof(DayOfWeek)))
|
||||||
{
|
{
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<button class="@(
|
<button class="@(
|
||||||
days.Contains(day)
|
days.Contains(day)
|
||||||
? "btn btn-secondary"
|
? "btn btn-secondary"
|
||||||
: "btn btn-outline-secondary"
|
: "btn btn-outline-secondary"
|
||||||
@@ -152,19 +153,16 @@
|
|||||||
else
|
else
|
||||||
days.Add(day);
|
days.Add(day);
|
||||||
}">
|
}">
|
||||||
@day
|
@day
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<button
|
<button @onclick="YamlTrigger" class="btn btn-primary">
|
||||||
@onclick="YamlTrigger"
|
Save Yaml File
|
||||||
class="btn btn-primary"
|
</button>
|
||||||
>
|
</div>
|
||||||
Save Yaml File
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@using Management.Web.Shared.Components
|
@using Management.Web.Shared.Components
|
||||||
|
@using Management.Web.Shared.Components.Forms
|
||||||
|
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
|
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
LockAt = null,
|
LockAt = null,
|
||||||
DueAt = DateTime.Now,
|
DueAt = DateTime.Now,
|
||||||
PointsPossible = 10,
|
PointsPossible = 10,
|
||||||
SubmissionTypes = new string[] { SubmissionType.ONLINE_TEXT_ENTRY }
|
SubmissionTypes = new string[] { SubmissionType.ONLINE_TEXT_ENTRY },
|
||||||
|
LocalAssignmentGroupId = selectedAssignmentGroup?.Id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(planner.LocalCourse != null)
|
if(planner.LocalCourse != null)
|
||||||
@@ -49,7 +51,14 @@
|
|||||||
Name = "";
|
Name = "";
|
||||||
modal?.Hide();
|
modal?.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setAssignmentGroup(LocalAssignmentGroup? group)
|
||||||
|
{
|
||||||
|
selectedAssignmentGroup = group;
|
||||||
|
}
|
||||||
|
private LocalAssignmentGroup? selectedAssignmentGroup { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-outline-secondary"
|
class="btn btn-outline-secondary"
|
||||||
@onclick="() => modal?.Show()"
|
@onclick="() => modal?.Show()"
|
||||||
@@ -64,6 +73,14 @@
|
|||||||
<label for="Assignment Name">Name</label>
|
<label for="Assignment Name">Name</label>
|
||||||
<input id="moduleName" class="form-control" @bind="Name" />
|
<input id="moduleName" class="form-control" @bind="Name" />
|
||||||
</form>
|
</form>
|
||||||
|
<br>
|
||||||
|
<label class="form-label">Assignment Group</label>
|
||||||
|
<ButtonSelect
|
||||||
|
Label="Assignment Group"
|
||||||
|
Options="planner.LocalCourse.Settings.AssignmentGroups"
|
||||||
|
GetName="(g) => g?.Name"
|
||||||
|
OnSelect="(g) => setAssignmentGroup(g)"
|
||||||
|
/>
|
||||||
</Body>
|
</Body>
|
||||||
<Footer>
|
<Footer>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
modal?.Hide();
|
modal?.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setAssignmentGroup(LocalAssignmentGroup? group)
|
private void setAssignmentGroup(LocalAssignmentGroup? group)
|
||||||
{
|
{
|
||||||
selectedAssignmentGroup = group;
|
selectedAssignmentGroup = group;
|
||||||
@@ -69,9 +68,9 @@
|
|||||||
<form @onsubmit:preventDefault="true" @onsubmit="submitHandler">
|
<form @onsubmit:preventDefault="true" @onsubmit="submitHandler">
|
||||||
<label for="Assignment Name">Name</label>
|
<label for="Assignment Name">Name</label>
|
||||||
<input id="moduleName" class="form-control" @bind="Name" />
|
<input id="moduleName" class="form-control" @bind="Name" />
|
||||||
<br>
|
|
||||||
<label class="form-label">Assignment Group</label>
|
|
||||||
</form>
|
</form>
|
||||||
|
<br>
|
||||||
|
<label class="form-label">Assignment Group</label>
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
Label="Assignment Group"
|
Label="Assignment Group"
|
||||||
Options="planner.LocalCourse.Settings.AssignmentGroups"
|
Options="planner.LocalCourse.Settings.AssignmentGroups"
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ namespace Management.Planner;
|
|||||||
|
|
||||||
public class CoursePlanner
|
public class CoursePlanner
|
||||||
{
|
{
|
||||||
private readonly YamlManager yamlManager;
|
private readonly FileStorageManager fileStorageManager;
|
||||||
private readonly CanvasService canvas;
|
private readonly CanvasService canvas;
|
||||||
public bool LoadingCanvasData { get; internal set; } = false;
|
public bool LoadingCanvasData { get; internal set; } = false;
|
||||||
|
|
||||||
public CoursePlanner(YamlManager yamlManager, CanvasService canvas)
|
public CoursePlanner(FileStorageManager fileStorageManager, CanvasService canvas)
|
||||||
{
|
{
|
||||||
this.yamlManager = yamlManager;
|
this.fileStorageManager = fileStorageManager;
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,12 +61,12 @@ public class CoursePlanner
|
|||||||
if (LocalCourse == null)
|
if (LocalCourse == null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("saving course as of debounce call time");
|
Console.WriteLine("saving course as of debounce call time");
|
||||||
await yamlManager.SaveCourseAsync(courseAsOfDebounce);
|
await fileStorageManager.SaveCourseAsync(courseAsOfDebounce);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Saving latest version of file");
|
Console.WriteLine("Saving latest version of file");
|
||||||
await yamlManager.SaveCourseAsync(LocalCourse);
|
await fileStorageManager.SaveCourseAsync(LocalCourse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace LocalModels;
|
|||||||
|
|
||||||
public record LocalQuizQuestion
|
public record LocalQuizQuestion
|
||||||
{
|
{
|
||||||
public string Id { get; set; } = "";
|
|
||||||
public string Text { get; init; } = string.Empty;
|
public string Text { get; init; } = string.Empty;
|
||||||
public string HtmlText => Markdig.Markdown.ToHtml(Text);
|
public string HtmlText => Markdig.Markdown.ToHtml(Text);
|
||||||
public string QuestionType { get; init; } = string.Empty;
|
public string QuestionType { get; init; } = string.Empty;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using LocalModels;
|
|||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
using YamlDotNet.Serialization.NamingConventions;
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
|
||||||
public class YamlManager
|
public class FileStorageManager
|
||||||
{
|
{
|
||||||
public string CourseToYaml(LocalCourse course)
|
public string CourseToYaml(LocalCourse course)
|
||||||
{
|
{
|
||||||
@@ -66,10 +66,6 @@ public class YamlManager
|
|||||||
|
|
||||||
foreach (var quiz in module.Quizzes)
|
foreach (var quiz in module.Quizzes)
|
||||||
{
|
{
|
||||||
var filePath = quizzesDirectory + "/" + quiz.Name + ".yml"; ;
|
|
||||||
var quizYaml = quiz.ToYaml();
|
|
||||||
await File.WriteAllTextAsync(filePath, quizYaml);
|
|
||||||
|
|
||||||
var markdownPath = quizzesDirectory + "/" + quiz.Name + ".md"; ;
|
var markdownPath = quizzesDirectory + "/" + quiz.Name + ".md"; ;
|
||||||
var quizMarkdown = quiz.ToMarkdown();
|
var quizMarkdown = quiz.ToMarkdown();
|
||||||
await File.WriteAllTextAsync(markdownPath, quizMarkdown);
|
await File.WriteAllTextAsync(markdownPath, quizMarkdown);
|
||||||
Reference in New Issue
Block a user