Skip to content

Commit 48d4811

Browse files
committed
fix merge conflicts
2 parents 9e7dead + 6f13160 commit 48d4811

File tree

10 files changed

+82
-61
lines changed

10 files changed

+82
-61
lines changed

Diff for: lms/lmsdb/bootstrap.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,8 @@ def _add_exercise_course_id_and_number_columns_constraint() -> bool:
296296
migrate(
297297
migrator.add_index('exercise', ('course_id', 'number'), True),
298298
)
299-
except OperationalError as e:
300-
if 'already exists' in str(e):
301-
log.info(f'index exercise already exists: {e}')
302-
else:
303-
raise
299+
except (OperationalError, ProgrammingError) as e:
300+
log.info(f'Index exercise course and number already exists: {e}')
304301
db_config.database.commit()
305302

306303

@@ -313,11 +310,8 @@ def _add_user_course_constaint() -> bool:
313310
'usercourse', ('user_id', 'course_id'), True,
314311
),
315312
)
316-
except OperationalError as e:
317-
if 'already exists' in str(e):
318-
log.info(f'index usercourse already exists: {e}')
319-
else:
320-
raise
313+
except (OperationalError, ProgrammingError) as e:
314+
log.info(f'Index usercourse user and course already exists: {e}')
321315
db_config.database.commit()
322316

323317

Diff for: lms/lmsdb/models.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -655,16 +655,11 @@ def view_solution(self) -> None:
655655
def start_checking(self) -> bool:
656656
return self.set_state(Solution.STATES.IN_CHECKING)
657657

658-
def set_state(
659-
self, new_state: SolutionState,
660-
assessment: Optional[SolutionAssessment] = None, **kwargs,
661-
) -> bool:
658+
def set_state(self, new_state: SolutionState, **kwargs) -> bool:
662659
# Optional: filter the old state of the object
663660
# to make sure that no two processes set the state together
664661
requested_solution = (Solution.id == self.id)
665662
updates_dict = {Solution.state.name: new_state.name}
666-
if assessment is not None:
667-
updates_dict[Solution.assessment.name] = assessment
668663
changes = Solution.update(
669664
**updates_dict, **kwargs,
670665
).where(requested_solution)
@@ -807,19 +802,20 @@ def _base_next_unchecked(cls):
807802
cls.submission_timestamp.asc(),
808803
)
809804

805+
def change_assessment(self, assessment_id: Optional[int] = None) -> bool:
806+
assessment = SolutionAssessment.get_or_none(
807+
SolutionAssessment.id == assessment_id,
808+
)
809+
requested_solution = (Solution.id == self.id)
810+
updates_dict = {Solution.assessment.name: assessment}
811+
changes = Solution.update(**updates_dict).where(requested_solution)
812+
return changes.execute() == 1
813+
810814
def mark_as_checked(
811815
self,
812-
assessment_id: Optional[int] = None,
813816
by: Optional[Union[User, int]] = None,
814817
) -> bool:
815-
assessment = SolutionAssessment.get_or_none(
816-
SolutionAssessment.id == assessment_id,
817-
)
818-
return self.set_state(
819-
Solution.STATES.DONE,
820-
assessment=assessment,
821-
checker=by,
822-
)
818+
return self.set_state(Solution.STATES.DONE, checker=by)
823819

824820
@classmethod
825821
def next_unchecked(cls) -> Optional['Solution']:

Diff for: lms/lmsweb/translations/he/LC_MESSAGES/messages.po

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: 1.0\n"
99
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10-
"POT-Creation-Date: 2021-10-11 10:38+0300\n"
10+
"POT-Creation-Date: 2021-10-15 14:37+0300\n"
1111
"PO-Revision-Date: 2021-09-29 11:30+0300\n"
1212
"Last-Translator: Or Ronai\n"
1313
"Language: he\n"
@@ -127,7 +127,7 @@ msgstr "%(solver)s הגיב לך על בדיקת תרגיל \"%(subject)s\"."
127127
msgid "%(checker)s replied for \"%(subject)s\"."
128128
msgstr "%(checker)s הגיב לך על תרגיל \"%(subject)s\"."
129129

130-
#: models/solutions.py:75
130+
#: models/solutions.py:78
131131
#, python-format
132132
msgid "Your solution for the \"%(subject)s\" exercise has been checked."
133133
msgstr "הפתרון שלך לתרגיל \"%(subject)s\" נבדק."

Diff for: lms/lmsweb/views.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -692,17 +692,20 @@ def shared_solution(shared_url: str, file_id: Optional[int] = None):
692692
)
693693

694694

695+
@webapp.route('/assessment/<int:solution_id>', methods=['POST'])
696+
@login_required
697+
@managers_only
698+
def assessment(solution_id: int):
699+
assessment_id = request.json.get('assessment')
700+
updated = solutions.change_assessment(solution_id, assessment_id)
701+
return jsonify({'success': updated})
702+
703+
695704
@webapp.route('/checked/<int:exercise_id>/<int:solution_id>', methods=['POST'])
696705
@login_required
697706
@managers_only
698-
def done_checking(exercise_id, solution_id):
699-
if request.method == 'POST':
700-
assessment_id = request.json.get('assessment')
701-
else: # it's a GET
702-
assessment_id = request.args.get('assessment')
703-
is_updated = solutions.mark_as_checked(
704-
solution_id, current_user.id, assessment_id,
705-
)
707+
def done_checking(exercise_id: int, solution_id: int):
708+
is_updated = solutions.mark_as_checked(solution_id, current_user.id)
706709
next_solution = solutions.get_next_unchecked(exercise_id)
707710
next_solution_id = getattr(next_solution, 'id', None)
708711
return jsonify({'success': is_updated, 'next': next_solution_id})

Diff for: lms/models/solutions.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,16 @@ def get_message_and_addressee(
6565
return msg, addressee
6666

6767

68-
def mark_as_checked(
69-
solution_id: int, checker_id: int, assessment_id: Optional[int] = None,
68+
def change_assessment(
69+
solution_id: int, assessment_id: Optional[int] = None,
7070
) -> bool:
7171
checked_solution: Solution = Solution.get_by_id(solution_id)
72-
is_updated = checked_solution.mark_as_checked(
73-
assessment_id=assessment_id, by=checker_id,
74-
)
72+
return checked_solution.change_assessment(assessment_id=assessment_id)
73+
74+
75+
def mark_as_checked(solution_id: int, checker_id: int) -> bool:
76+
checked_solution: Solution = Solution.get_by_id(solution_id)
77+
is_updated = checked_solution.mark_as_checked(by=checker_id)
7578
msg = _(
7679
'Your solution for the "%(subject)s" exercise has been checked.',
7780
subject=checked_solution.exercise.subject,

Diff for: lms/static/checker.js

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
function trackFinished(exerciseId, solutionId, element) {
22
element.addEventListener('click', () => {
3-
const assessment = document.querySelector('input[name="assessment"]:checked');
4-
const assessmentValue = (assessment !== null) ? assessment.value : null;
53
const xhr = new XMLHttpRequest();
64
xhr.open('POST', `/checked/${exerciseId}/${solutionId}`, true);
75
xhr.setRequestHeader('Content-Type', 'application/json');
@@ -20,20 +18,33 @@ function trackFinished(exerciseId, solutionId, element) {
2018
}
2119
};
2220

23-
xhr.send(JSON.stringify({
24-
assessment: assessmentValue,
25-
}));
21+
xhr.send(JSON.stringify({}));
2622
});
2723
}
2824

2925
function changeAssessmentsAttributes(assessmentGroup, item) {
3026
if (item.value == assessmentGroup.dataset.checkedid) {
3127
item.removeAttribute('checked');
3228
item.checked = false;
33-
assessmentGroup.dataset.checkedid = 'None';
29+
assessmentGroup.dataset.checkedid = null;
3430
} else {
3531
assessmentGroup.dataset.checkedid = item.value;
3632
}
33+
document.activeElement.blur();
34+
35+
const xhr = new XMLHttpRequest();
36+
xhr.open('POST', `/assessment/${solutionId}`, true);
37+
xhr.setRequestHeader('Content-Type', 'application/json');
38+
xhr.responseType = 'json';
39+
xhr.onreadystatechange = () => {
40+
if (xhr.readyState === 4) {
41+
if (xhr.status !== 200) {
42+
console.log(xhr.status);
43+
}
44+
}
45+
};
46+
47+
xhr.send(JSON.stringify({assessment: assessmentGroup.dataset.checkedid}));
3748
}
3849

3950
function trackAssessmentButtons() {

Diff for: lms/static/my.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ code .grader-add .fa {
795795
}
796796

797797
#courses-list {
798-
overflow-y: scroll;
798+
overflow-y: auto;
799799
max-height: 10em;
800800
}
801801

Diff for: lms/templates/view.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{% block page_content %}
44
<div id="page-view">
55
<div id="view-head">
6-
<h1>{{ _('Exercise view') }} {{ solution['exercise']['id'] }}: {{ solution['exercise']['subject'] }}</h1>
6+
<h1>{{ _('Exercise view') }} {{ solution['exercise']['number'] }}: {{ solution['exercise']['subject'] }}</h1>
77
{% if not is_manager and not shared_url %}
88
{% if solution['state'] == 'DONE' %}
99
<p class="checked-msg {{ direction }}"><strong>{{ _('Your solution had checked!') }}</strong> {{ _('Click on the red lines in order to see the comments.') }}</p>

Diff for: tests/test_notifications.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def test_user_commented_after_check(
178178
client = conftest.get_logged_user(student_user.username)
179179

180180
# Marking the solution as checked
181-
solutions.mark_as_checked(solution.id, staff_user.id, 1)
181+
solutions.mark_as_checked(solution.id, staff_user.id)
182182
solution = Solution.get_by_id(solution.id)
183183

184184
# Sending comments after solution checked

Diff for: tests/test_solutions.py

+26-12
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def test_mark_as_checked(
132132
):
133133
# Basic functionality
134134
assert solution.state == Solution.STATES.CREATED.name
135-
marked = solutions.mark_as_checked(solution.id, staff_user.id, 2)
135+
marked = solutions.mark_as_checked(solution.id, staff_user.id)
136136
# HELL WITH PEEWEE!!!
137137
solution = Solution.get_by_id(solution.id)
138138
assert marked
@@ -142,7 +142,7 @@ def test_mark_as_checked(
142142
# Not duplicating things
143143
staff_user2 = conftest.create_staff_user(index=1)
144144
solution2 = conftest.create_solution(exercise, student_user)
145-
marked = solutions.mark_as_checked(solution2.id, staff_user2.id, 3)
145+
marked = solutions.mark_as_checked(solution2.id, staff_user2.id)
146146
solution2 = Solution.get_by_id(solution2.id)
147147
assert solution2.state == Solution.STATES.DONE.name
148148
assert solution2.checker == staff_user2
@@ -171,21 +171,21 @@ def test_get_next_unchecked(
171171
assert unchecked.exercise.id == solution1.exercise.id
172172
assert unchecked == solution1
173173

174-
solutions.mark_as_checked(solution1.id, staff_user, 4)
174+
solutions.mark_as_checked(solution1.id, staff_user)
175175
unchecked = solutions.get_next_unchecked(exercise.id)
176176
assert unchecked is not None
177177
assert unchecked.exercise.id == solution3.exercise.id
178178
assert unchecked == solution3
179179

180-
solutions.mark_as_checked(solution3.id, staff_user, 1)
180+
solutions.mark_as_checked(solution3.id, staff_user)
181181
unchecked = solutions.get_next_unchecked(exercise.id)
182182
assert unchecked is None
183183

184184
unchecked = solutions.get_next_unchecked()
185185
assert unchecked is not None
186186
assert unchecked == solution2
187187

188-
solutions.mark_as_checked(solution2.id, staff_user, 2)
188+
solutions.mark_as_checked(solution2.id, staff_user)
189189
unchecked = solutions.get_next_unchecked()
190190
assert unchecked is None
191191

@@ -563,7 +563,7 @@ def test_last_view_status(
563563
solution = Solution.get_by_id(solution.id)
564564
assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name
565565

566-
solutions.mark_as_checked(solution.id, staff_user.id, 3)
566+
solutions.mark_as_checked(solution.id, staff_user.id)
567567
solution = Solution.get_by_id(solution.id)
568568
assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name
569569
client.get(f'/view/{solution.id}')
@@ -590,8 +590,6 @@ def test_done_checking(
590590
client = conftest.get_logged_user(staff_user.username)
591591
response = client.post(
592592
f'/checked/{solution.exercise.id}/{solution.id}',
593-
data=json.dumps({'assessment': 1}),
594-
content_type='application/json',
595593
)
596594
assert response.status_code == 200
597595

@@ -636,14 +634,30 @@ def test_solutions_of_user(
636634
solution: Solution, _assessments,
637635
):
638636
conftest.create_usercourse(student_user, course)
639-
solutions.mark_as_checked(solution.id, staff_user.id, 2)
637+
client = conftest.get_logged_user(staff_user.username)
638+
client.post(
639+
f'/assessment/{solution.id}',
640+
data=json.dumps({'assessment': 2}),
641+
content_type='application/json',
642+
)
640643
solution = Solution.get_by_id(solution.id)
644+
assert solution.assessment.name == 'Nice'
645+
646+
client.post(
647+
f'/assessment/{solution.id}',
648+
data=json.dumps({'assessment': None}),
649+
content_type='application/json',
650+
)
641651

642652
exercise2 = conftest.create_exercise(course, 2)
643653
solution2 = conftest.create_solution(exercise2, student_user)
644-
solutions.mark_as_checked(solution2.id, staff_user.id)
654+
client.post(
655+
f'/assessment/{solution2.id}',
656+
data=json.dumps({'assessment': 3}),
657+
content_type='application/json',
658+
)
645659
solution2 = Solution.get_by_id(solution2.id)
646660

647661
exercises = solution.of_user(student_user.id, from_all_courses=True)
648-
assert exercises[0].get('assessment') == 'Nice'
649-
assert exercises[1].get('assessment') is None
662+
assert exercises[0].get('assessment') is None
663+
assert exercises[1].get('assessment') == 'Try again'

0 commit comments

Comments
 (0)