Skip to content

Commit d4f2397

Browse files
committed
RE1-T112 PR#321 fixes
1 parent 6fdcc9d commit d4f2397

6 files changed

Lines changed: 84 additions & 66 deletions

File tree

Providers/Resgrid.Providers.Weather/EnvironmentCanadaWeatherAlertProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ private async Task<List<WeatherAlert>> FetchAndParseCapDocumentAsync(string capU
233233
if (geocodes.Any())
234234
{
235235
alert.Geocodes = System.Text.Json.JsonSerializer.Serialize(
236-
geocodes.ToDictionary(g => g.Name, g => g.Value));
236+
geocodes.GroupBy(g => g.Name).ToDictionary(g => g.Key, g => g.Last().Value));
237237
}
238238
}
239239

Web/Resgrid.Web/Areas/User/Controllers/TrainingsController.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ public async Task<IActionResult> View(int trainingId)
224224
{
225225
var model = new ViewTrainingModel();
226226
model.Training = await _trainingService.GetTrainingByIdAsync(trainingId);
227+
228+
if (model.Training == null)
229+
return NotFound();
230+
227231
model.CreatorUserName = await UserHelper.GetFullNameForUser(model.Training.CreatedByUserId);
228232

229233
if (model.Training.DepartmentId != DepartmentId)
@@ -302,9 +306,9 @@ public async Task<IActionResult> Edit(int trainingId, EditTrainingModel model, I
302306
attachment.FileName = file.FileName;
303307
attachment.TrainingId = trainingId;
304308

305-
using var stream = file.OpenReadStream();
306-
var uploadedFile = new byte[stream.Length];
307-
stream.Read(uploadedFile, 0, uploadedFile.Length);
309+
using var stream = file.OpenReadStream();
310+
var uploadedFile = new byte[stream.Length];
311+
await stream.ReadAsync(uploadedFile, 0, uploadedFile.Length);
308312

309313
attachment.Data = uploadedFile;
310314
existingTraining.Attachments.Add(attachment);
@@ -485,6 +489,9 @@ public async Task<IActionResult> Quiz(int trainingId, CancellationToken cancella
485489
var model = new ViewTrainingModel();
486490
model.Training = await _trainingService.GetTrainingByIdAsync(trainingId);
487491

492+
if (model.Training == null)
493+
return NotFound();
494+
488495
if (model.Training.DepartmentId != DepartmentId)
489496
return Unauthorized();
490497

@@ -499,7 +506,10 @@ public async Task<IActionResult> Quiz(ViewTrainingModel model, IFormCollection f
499506
{
500507
int correctAnswers = 0;
501508
var training = await _trainingService.GetTrainingByIdAsync(model.Training.TrainingId);
502-
509+
510+
if (training == null)
511+
return NotFound();
512+
503513
List<int> questions = (from object key in form.Keys where key.ToString().StartsWith("question_") select int.Parse(key.ToString().Replace("question_", ""))).ToList();
504514

505515
foreach (var questionId in questions)
@@ -529,6 +539,9 @@ public async Task<IActionResult> DeleteTraining(int trainingId)
529539
var model = new ViewTrainingModel();
530540
model.Training = await _trainingService.GetTrainingByIdAsync(trainingId);
531541

542+
if (model.Training == null)
543+
return NotFound();
544+
532545
if (model.Training.DepartmentId != DepartmentId)
533546
return Unauthorized();
534547

@@ -543,6 +556,9 @@ public async Task<IActionResult> ResetUserTraining(int trainingId, string userId
543556
var model = new ViewTrainingModel();
544557
model.Training = await _trainingService.GetTrainingByIdAsync(trainingId);
545558

559+
if (model.Training == null)
560+
return NotFound();
561+
546562
if (model.Training.DepartmentId != DepartmentId)
547563
return Unauthorized();
548564

@@ -556,6 +572,10 @@ public async Task<IActionResult> Report(int trainingId)
556572
{
557573
var model = new TrainingReportView();
558574
model.Training = await _trainingService.GetTrainingByIdAsync(trainingId);
575+
576+
if (model.Training == null)
577+
return NotFound();
578+
559579
model.UserGroups = new Dictionary<string, string>();
560580
model.Department = await _departmentsService.GetDepartmentByIdAsync(DepartmentId, false);
561581

Web/Resgrid.Web/Areas/User/Views/Trainings/Edit.cshtml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,18 +270,19 @@
270270
@section Scripts
271271
{
272272
<script>
273-
var resgridTrainingsI18n = {
274-
selectGroups: '@localizer["SelectGroupsPlaceholder"]',
275-
selectRoles: '@localizer["SelectRolesPlaceholder"]',
276-
selectUsers: '@localizer["SelectUsersPlaceholder"]',
277-
removeQuestionTooltip: '@localizer["RemoveQuestionTooltip"]',
278-
removeAnswerTooltip: '@localizer["RemoveAnswerTooltip"]',
279-
addAnswer: '@localizer["AddAnswerButton"]',
280-
answerRequired: '@localizer["AnswerRequiredMessage"]',
281-
addQuestionTooltip: '@localizer["AddQuestionTooltip"]',
282-
correct: '@localizer["CorrectLabel"]',
283-
answerText: '@localizer["AnswerTextColumn"]'
284-
};
273+
var resgridTrainingsI18n = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(new {
274+
selectGroups = localizer["SelectGroupsPlaceholder"].Value,
275+
selectRoles = localizer["SelectRolesPlaceholder"].Value,
276+
selectUsers = localizer["SelectUsersPlaceholder"].Value,
277+
removeQuestionTooltip = localizer["RemoveQuestionTooltip"].Value,
278+
removeAnswerTooltip = localizer["RemoveAnswerTooltip"].Value,
279+
addAnswer = localizer["AddAnswerButton"].Value,
280+
answerRequired = localizer["AnswerRequiredMessage"].Value,
281+
addQuestionTooltip = localizer["AddQuestionTooltip"].Value,
282+
addAnswerTooltip = localizer["AddAnswerTooltip"].Value,
283+
correct = localizer["CorrectLabel"].Value,
284+
answerText = localizer["AnswerTextColumn"].Value
285+
}));
285286
</script>
286287
<script src="~/js/app/internal/training/resgrid.training.edittraining.js"></script>
287288
}

Web/Resgrid.Web/Areas/User/Views/Trainings/New.cshtml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,18 +198,19 @@
198198
@section Scripts
199199
{
200200
<script>
201-
var resgridTrainingsI18n = {
202-
selectGroups: '@localizer["SelectGroupsPlaceholder"]',
203-
selectRoles: '@localizer["SelectRolesPlaceholder"]',
204-
selectUsers: '@localizer["SelectUsersPlaceholder"]',
205-
removeQuestionTooltip: '@localizer["RemoveQuestionTooltip"]',
206-
removeAnswerTooltip: '@localizer["RemoveAnswerTooltip"]',
207-
addAnswer: '@localizer["AddAnswerButton"]',
208-
answerRequired: '@localizer["AnswerRequiredMessage"]',
209-
addQuestionTooltip: '@localizer["AddQuestionTooltip"]',
210-
correct: '@localizer["CorrectLabel"]',
211-
answerText: '@localizer["AnswerTextColumn"]'
212-
};
201+
var resgridTrainingsI18n = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(new {
202+
selectGroups = localizer["SelectGroupsPlaceholder"].Value,
203+
selectRoles = localizer["SelectRolesPlaceholder"].Value,
204+
selectUsers = localizer["SelectUsersPlaceholder"].Value,
205+
removeQuestionTooltip = localizer["RemoveQuestionTooltip"].Value,
206+
removeAnswerTooltip = localizer["RemoveAnswerTooltip"].Value,
207+
addAnswer = localizer["AddAnswerButton"].Value,
208+
answerRequired = localizer["AnswerRequiredMessage"].Value,
209+
addQuestionTooltip = localizer["AddQuestionTooltip"].Value,
210+
addAnswerTooltip = localizer["AddAnswerTooltip"].Value,
211+
correct = localizer["CorrectLabel"].Value,
212+
answerText = localizer["AnswerTextColumn"].Value
213+
}));
213214
</script>
214215
<script src="~/js/app/internal/training/resgrid.training.newtraining.js"></script>
215216
}

Web/Resgrid.Web/wwwroot/js/app/internal/training/resgrid.training.edittraining.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ var resgrid;
66
(function (edittraining) {
77
var i18n = (typeof resgridTrainingsI18n !== 'undefined') ? resgridTrainingsI18n : {};
88

9+
function escapeHtml(str) {
10+
if (!str) return '';
11+
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
12+
}
13+
914
$(document).ready(function () {
1015
resgrid.common.analytics.track('Training - Edit');
1116

@@ -46,7 +51,7 @@ var resgrid;
4651
$('#rolesToAdd').prop('disabled', false).trigger('change.select2');
4752
$('#usersToAdd').prop('disabled', false).trigger('change.select2');
4853
}
49-
});
54+
}).trigger('change');
5055

5156
function initSelect2(selector, placeholder, url) {
5257
$(selector).select2({
@@ -81,41 +86,34 @@ var resgrid;
8186
resgrid.training.edittraining.questionsCount = maxIndex;
8287
});
8388
function addQuestion() {
84-
var removeTooltip = i18n.removeQuestionTooltip || 'Remove this question';
89+
var removeTooltip = escapeHtml(i18n.removeQuestionTooltip || 'Remove this question');
8590
resgrid.training.edittraining.questionsCount++;
8691
$('#questions tbody').first().append("<tr><td style='max-width: 215px;'><textarea id='question_" + edittraining.questionsCount + "' name='question_" + edittraining.questionsCount + "' rows='4' cols='40'></textarea></td><td>" + resgrid.training.edittraining.generateAnswersTable(edittraining.questionsCount) + "</td><td style='text-align:center;'><a onclick='$(this).parent().parent().remove();' class='tip-top' data-original-title='" + removeTooltip + "'><i class='fa fa-minus' style='color: red;'></i></a></td></tr>");
8792
}
8893
edittraining.addQuestion = addQuestion;
8994
function generateAnswersTable(count) {
90-
var addAnswerLabel = i18n.addAnswer || 'Add Answer';
91-
var addAnswerTooltip = i18n.addQuestionTooltip || 'Add Answers to Question';
92-
var correctLabel = i18n.correct || 'Correct';
93-
var answerTextLabel = i18n.answerText || 'Answer Text';
94-
var answersTable = '<table id="answersTable_' + count + '" class="table table-striped table-bordered"><thead><tr><th style="max-width:35px;font-size: 14px;" >' + correctLabel + '</th><th style = "font-size: 14px;" >' + answerTextLabel + '</th><th style = "font-size: 16px;" ><a id="addAnswerButton" class="btn btn-success btn-xs" onclick="resgrid.training.edittraining.addAnswer(' + count + ');" data-original-title="' + addAnswerTooltip + '" ><i class="icon-plus" ></i> ' + addAnswerLabel + '</a></th></tr></thead><tbody></tbody></table>';
95+
var addAnswerLabel = escapeHtml(i18n.addAnswer || 'Add Answer');
96+
var addAnswerTooltip = escapeHtml(i18n.addAnswerTooltip || 'Add Answers to Question');
97+
var correctLabel = escapeHtml(i18n.correct || 'Correct');
98+
var answerTextLabel = escapeHtml(i18n.answerText || 'Answer Text');
99+
var answersTable = '<table id="answersTable_' + count + '" class="table table-striped table-bordered"><thead><tr><th style="max-width:35px;font-size: 14px;" >' + correctLabel + '</th><th style = "font-size: 14px;" >' + answerTextLabel + '</th><th style = "font-size: 16px;" ><a id="addAnswerButton_' + count + '" class="btn btn-success btn-xs" onclick="resgrid.training.edittraining.addAnswer(' + count + ');" data-original-title="' + addAnswerTooltip + '" ><i class="icon-plus" ></i> ' + addAnswerLabel + '</a></th></tr></thead><tbody></tbody></table>';
95100
return answersTable;
96101
}
97102
edittraining.generateAnswersTable = generateAnswersTable;
98103
function addAnswer(count) {
99104
var id = generate(4);
100-
var answerRequired = i18n.answerRequired || 'Answer is required';
101-
var removeAnswerTooltip = i18n.removeAnswerTooltip || 'Remove this answer from the question';
105+
var answerRequired = escapeHtml(i18n.answerRequired || 'Answer is required');
106+
var removeAnswerTooltip = escapeHtml(i18n.removeAnswerTooltip || 'Remove this answer from the question');
102107
$('#answersTable_' + count + ' tbody').append("<tr><td><input type='radio' name='answer_" + count + "' value='answerForQuestion_" + count + "_" + id + "'></td><td><textarea rows='3' cols='30' data-bv-notempty data-bv-notempty-message='" + answerRequired + "' id='answerForQuestion_" + count + "_" + id + "' name='answerForQuestion_" + count + "_" + id + "'></textarea></td><td style='text-align:center;'><a onclick='$(this).parent().parent().remove();' class='tip-top' data-original-title='" + removeAnswerTooltip + "'><i class='fa fa-minus' style='color: red;'></i></a></td></tr>");
103108
}
104109
edittraining.addAnswer = addAnswer;
105110
function removeQuestion(index) {
106111
$('#questionRow_' + index).remove();
107112
}
108113
edittraining.removeQuestion = removeQuestion;
109-
function generate(length) {
110-
var arr = [];
111-
var n;
112-
for (var i = 0; i < length; i++) {
113-
do
114-
n = Math.floor(Math.random() * 20 + 1);
115-
while (arr.indexOf(n) !== -1);
116-
arr[i] = n;
117-
}
118-
return arr.join('');
114+
var _answerIdCounter = 0;
115+
function generate() {
116+
return ++_answerIdCounter;
119117
}
120118
edittraining.generate = generate;
121119
})(edittraining = training.edittraining || (training.edittraining = {}));

Web/Resgrid.Web/wwwroot/js/app/internal/training/resgrid.training.newtraining.js

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ var resgrid;
77
(function (newtraining) {
88
var i18n = (typeof resgridTrainingsI18n !== 'undefined') ? resgridTrainingsI18n : {};
99

10+
function escapeHtml(str) {
11+
if (!str) return '';
12+
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
13+
}
14+
1015
$(document).ready(function () {
1116
resgrid.common.analytics.track('Training - New');
1217

@@ -73,37 +78,30 @@ var resgrid;
7378
resgrid.training.newtraining.questionsCount = 0;
7479
});
7580
function addQuestion() {
76-
var removeTooltip = i18n.removeQuestionTooltip || 'Remove this question';
81+
var removeTooltip = escapeHtml(i18n.removeQuestionTooltip || 'Remove this question');
7782
resgrid.training.newtraining.questionsCount++;
7883
$('#questions tbody').first().append("<tr><td style='max-width: 215px;'><textarea id='question_" + newtraining.questionsCount + "' name='question_" + newtraining.questionsCount + "' rows='4' cols='40'></textarea></td><td>" + resgrid.training.newtraining.generateAnswersTable(newtraining.questionsCount) + "</td><td style='text-align:center;'><a onclick='$(this).parent().parent().remove();' class='tip-top' data-original-title='" + removeTooltip + "'><i class='fa fa-minus' style='color: red;'></i></a></td></tr>");
7984
}
8085
newtraining.addQuestion = addQuestion;
8186
function generateAnswersTable(count) {
82-
var addAnswerLabel = i18n.addAnswer || 'Add Answer';
83-
var addAnswerTooltip = i18n.addQuestionTooltip || 'Add Answers to Question';
84-
var correctLabel = i18n.correct || 'Correct';
85-
var answerTextLabel = i18n.answerText || 'Answer Text';
86-
var answersTable = '<table id="answersTable_' + count + '" class="table table-striped table-bordered"><thead><tr><th style="max-width:35px;font-size: 14px;" >' + correctLabel + '</th><th style = "font-size: 14px;" >' + answerTextLabel + '</th><th style = "font-size: 16px;" ><a id="addAnswerButton" class="btn btn-success btn-xs" onclick="resgrid.training.newtraining.addAnswer(' + count + ');" data-original-title="' + addAnswerTooltip + '" ><i class="icon-plus" ></i> ' + addAnswerLabel + '</a></th></tr></thead><tbody></tbody></table>';
87+
var addAnswerLabel = escapeHtml(i18n.addAnswer || 'Add Answer');
88+
var addAnswerTooltip = escapeHtml(i18n.addAnswerTooltip || 'Add Answers to Question');
89+
var correctLabel = escapeHtml(i18n.correct || 'Correct');
90+
var answerTextLabel = escapeHtml(i18n.answerText || 'Answer Text');
91+
var answersTable = '<table id="answersTable_' + count + '" class="table table-striped table-bordered"><thead><tr><th style="max-width:35px;font-size: 14px;" >' + correctLabel + '</th><th style = "font-size: 14px;" >' + answerTextLabel + '</th><th style = "font-size: 16px;" ><a id="addAnswerButton_' + count + '" class="btn btn-success btn-xs" onclick="resgrid.training.newtraining.addAnswer(' + count + ');" data-original-title="' + addAnswerTooltip + '" ><i class="icon-plus" ></i> ' + addAnswerLabel + '</a></th></tr></thead><tbody></tbody></table>';
8792
return answersTable;
8893
}
8994
newtraining.generateAnswersTable = generateAnswersTable;
9095
function addAnswer(count) {
9196
var id = generate(4);
92-
var answerRequired = i18n.answerRequired || 'Answer is required';
93-
var removeAnswerTooltip = i18n.removeAnswerTooltip || 'Remove this answer from the question';
97+
var answerRequired = escapeHtml(i18n.answerRequired || 'Answer is required');
98+
var removeAnswerTooltip = escapeHtml(i18n.removeAnswerTooltip || 'Remove this answer from the question');
9499
$('#answersTable_' + count + ' tbody').append("<tr><td><input type='radio' name='answer_" + count + "' value='answerForQuestion_" + count + "_" + id + "'></td><td><textarea rows='3' cols='30' data-bv-notempty data-bv-notempty-message='" + answerRequired + "' id='answerForQuestion_" + count + "_" + id + "' name='answerForQuestion_" + count + "_" + id + "'></textarea></td><td style='text-align:center;'><a onclick='$(this).parent().parent().remove();' class='tip-top' data-original-title='" + removeAnswerTooltip + "'><i class='fa fa-minus' style='color: red;'></i></a></td></tr>");
95100
}
96101
newtraining.addAnswer = addAnswer;
97-
function generate(length) {
98-
var arr = [];
99-
var n;
100-
for (var i = 0; i < length; i++) {
101-
do
102-
n = Math.floor(Math.random() * 20 + 1);
103-
while (arr.indexOf(n) !== -1);
104-
arr[i] = n;
105-
}
106-
return arr.join('');
102+
var _answerIdCounter = 0;
103+
function generate() {
104+
return ++_answerIdCounter;
107105
}
108106
newtraining.generate = generate;
109107
})(newtraining = training.newtraining || (training.newtraining = {}));

0 commit comments

Comments
 (0)