Skip to content

Commit f647f9e

Browse files
authored
Merge branch 'master' into edit-profile
2 parents 791fd06 + 9499e89 commit f647f9e

File tree

14 files changed

+196
-113
lines changed

14 files changed

+196
-113
lines changed

devops/bootstrap.sh

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,22 @@ SCRIPT_FILE_PATH=$(readlink -f "${0}")
44
SCRIPT_FOLDER=$(dirname "${SCRIPT_FILE_PATH}")
55
MAIN_FOLDER="${SCRIPT_FOLDER}/../lms"
66

7-
docker exec -i lms_rabbitmq_1 rabbitmqctl add_vhost lmstests-public
8-
docker exec -i lms_rabbitmq_1 rabbitmqctl add_vhost lmstests-sandbox
9-
docker exec -i lms_rabbitmq_1 rabbitmqctl set_permissions -p lmstests-public rabbit-user ".*" ".*" ".*"
10-
docker exec -i lms_rabbitmq_1 rabbitmqctl set_permissions -p lmstests-sandbox rabbit-user ".*" ".*" ".*"
11-
docker exec -i lms_http_1 python lmsdb/bootstrap.py
7+
# Starting from docker-compose 2,
8+
# names are network-image-id instead of network_image_id
9+
if docker-compose --version | grep -q 'version 2'; then
10+
SEP="-"
11+
else
12+
SEP="_"
13+
fi
14+
15+
docker exec -i lms${SEP}rabbitmq${SEP}1 rabbitmqctl add_vhost lmstests-public
16+
docker exec -i lms${SEP}rabbitmq${SEP}1 rabbitmqctl add_vhost lmstests-sandbox
17+
docker exec -i lms${SEP}rabbitmq${SEP}1 rabbitmqctl set_permissions -p lmstests-public rabbit-user ".*" ".*" ".*"
18+
docker exec -i lms${SEP}rabbitmq${SEP}1 rabbitmqctl set_permissions -p lmstests-sandbox rabbit-user ".*" ".*" ".*"
19+
docker exec -i lms${SEP}http${SEP}1 python lmsdb/bootstrap.py
1220

1321
# build the image for docker inside a docker!
14-
docker exec lms_checks-docker-engine_1 mkdir -p /home/lms
15-
docker cp "${MAIN_FOLDER}"/lmstests/public/unittests/image/requirements.txt lms_checks-docker-engine_1:/home/lms/.
16-
docker cp "${MAIN_FOLDER}"/lmstests/public/unittests/image/Dockerfile lms_checks-docker-engine_1:/home/lms/.
17-
docker exec lms_checks-docker-engine_1 sh -c "cd /home/lms && docker build -t lms ."
22+
docker exec lms${SEP}checks-docker-engine${SEP}1 mkdir -p /home/lms
23+
docker cp "${MAIN_FOLDER}"/lmstests/public/unittests/image/requirements.txt lms${SEP}checks-docker-engine${SEP}1:/home/lms/.
24+
docker cp "${MAIN_FOLDER}"/lmstests/public/unittests/image/Dockerfile lms${SEP}checks-docker-engine${SEP}1:/home/lms/.
25+
docker exec lms${SEP}checks-docker-engine${SEP}1 sh -c "cd /home/lms && docker build -t lms ."

lms/lmsdb/bootstrap.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Callable, Optional, Tuple, Type
1+
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, Union
22
from uuid import uuid4
33

44
from peewee import (
@@ -328,25 +328,37 @@ def _avatar_migration() -> bool:
328328
return True
329329

330330

331+
def is_tables_exists(tables: Union[Model, Iterable[Model]]) -> bool:
332+
if not isinstance(tables, (tuple, list)):
333+
tables = (tables,)
334+
335+
return all(
336+
models.database.table_exists(table.__name__.lower())
337+
for table in tables
338+
)
339+
340+
341+
def get_new_tables(tables: Iterable[Model]) -> List[Model]:
342+
return [table for table in tables if not is_tables_exists(table)]
343+
344+
345+
331346
def main():
332347
with models.database.connection_context():
333-
if models.database.table_exists(models.Exercise.__name__.lower()):
334-
_add_exercise_course_id_and_number_columns_constraint()
348+
new_tables = get_new_tables(models.ALL_MODELS)
349+
models.database.create_tables(new_tables, safe=True)
335350

336-
if models.database.table_exists(models.Solution.__name__.lower()):
337-
_last_status_view_migration()
338-
_assessment_migration()
351+
_add_exercise_course_id_and_number_columns_constraint()
339352

340-
if models.database.table_exists(models.User.__name__.lower()):
341-
_api_keys_migration()
342-
_last_course_viewed_migration()
343-
_uuid_migration()
344-
_avatar_migration()
353+
_last_status_view_migration()
354+
_assessment_migration()
345355

346-
if models.database.table_exists(models.UserCourse.__name__.lower()):
347-
_add_user_course_constaint()
356+
_api_keys_migration()
357+
_last_course_viewed_migration()
358+
_uuid_migration()
359+
_avatar_migration()
348360

349-
models.database.create_tables(models.ALL_MODELS, safe=True)
361+
_add_user_course_constaint()
350362

351363
models.create_basic_roles()
352364
if models.User.select().count() == 0:

lms/lmsdb/models.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -799,26 +799,29 @@ def next_unchecked_of(cls, exercise_id) -> Optional['Solution']:
799799
return None
800800

801801
@classmethod
802-
def status(cls):
802+
def status(cls, course_id: Optional[int] = None):
803803
one_if_is_checked = Case(
804804
Solution.state, ((Solution.STATES.DONE.name, 1),), 0,
805805
)
806806
fields = (
807807
Exercise.id,
808+
Exercise.course,
808809
Exercise.subject.alias('name'),
809810
Exercise.is_archived.alias('is_archived'),
810811
fn.Count(Solution.id).alias('submitted'),
811812
fn.Sum(one_if_is_checked).alias('checked'),
812813
)
813-
join_by_exercise = (Solution.exercise == Exercise.id)
814-
active_solutions = Solution.state.in_(
815-
Solution.STATES.active_solutions(),
816-
)
814+
active_solution_states = Solution.STATES.active_solutions()
815+
active_solutions = Solution.state.in_(active_solution_states)
816+
right_course = (course_id is None) or course_id == Course.id
817+
817818
return (
818819
Exercise
819820
.select(*fields)
820-
.join(Solution, JOIN.LEFT_OUTER, on=join_by_exercise)
821-
.where(active_solutions)
821+
.join(Course, on=(Course.id == Exercise.course))
822+
.switch()
823+
.join(Solution, on=(Solution.exercise == Exercise.id))
824+
.where(active_solutions & right_course)
822825
.group_by(Exercise.subject, Exercise.id)
823826
.order_by(Exercise.id)
824827
)

lms/lmsweb/translations/he/LC_MESSAGES/messages.po

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@
55
#
66
msgid ""
77
msgstr ""
8-
"Project-Id-Version: 1.0\n"
8+
"Project-Id-Version: 1.0\n"
99
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
1010
"POT-Creation-Date: 2021-10-15 14:37+0300\n"
11-
"PO-Revision-Date: 2021-09-29 11:30+0300\n"
11+
"PO-Revision-Date: 2021-10-17 01:59+0300\n"
1212
"Last-Translator: Or Ronai\n"
1313
"Language: he\n"
1414
"Language-Team: he <[email protected]>\n"
15-
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
15+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
1616
"MIME-Version: 1.0\n"
1717
"Content-Type: text/plain; charset=utf-8\n"
1818
"Content-Transfer-Encoding: 8bit\n"
1919
"Generated-By: Babel 2.9.1\n"
20+
"X-Generator: Poedit 3.0\n"
21+
"X-Poedit-Bookmarks: -1,-1,-1,-1,0,-1,-1,-1,-1,-1\n"
2022

2123
#: lmsdb/models.py:926
2224
msgid "Fatal error"
@@ -39,8 +41,8 @@ msgstr "הבודק האוטומטי לא הצליח להריץ את הקוד ש
3941
#: lmstests/public/unittests/services.py:120
4042
#, python-format
4143
msgid ""
42-
"The automatic checker failed in %(number)d examples in your "
43-
"\"%(subject)s\" solution."
44+
"The automatic checker failed in %(number)d examples in your \"%(subject)s\" "
45+
"solution."
4446
msgstr "הבודק האוטומטי נכשל ב־ %(number)d דוגמאות בתרגיל \"%(subject)s\"."
4547

4648
#: lmstests/public/unittests/services.py:142
@@ -73,12 +75,12 @@ msgstr "קישור לאיפוס הסיסמה נשלח בהצלחה"
7375

7476
#: lmsweb/views.py:289
7577
msgid "Reset password link is expired"
76-
msgstr "קישור איפוס הסיסמה פג תוקף"
78+
msgstr "הקישור לאיפוס הסיסמה פג תוקף"
7779

7880
#: lmsweb/forms/change_password.py:20 lmsweb/forms/register.py:32
7981
#: lmsweb/forms/reset_password.py:25
8082
msgid "The passwords are not identical"
81-
msgstr "הסיסמאות שהוקלדו אינן זהות"
83+
msgstr "הסיסמאות שהוזנו אינן זהות"
8284

8385
#: lmsweb/forms/change_password.py:31
8486
msgid "Invalid old password has been inserted too many times"
@@ -91,7 +93,7 @@ msgstr "הסיסמה הנוכחית שהוזנה שגויה"
9193
#: lmsweb/forms/register.py:14 lmsweb/forms/reset_password.py:12
9294
#: lmsweb/tools/validators.py:29
9395
msgid "Invalid email"
94-
msgstr "אימייל לא תקין"
96+
msgstr "כתובת הדואר האלקטרוני שהוזנה אינה תקינה"
9597

9698
#: lmsweb/forms/update_avatar.py:14
9799
msgid "No file added"
@@ -104,11 +106,11 @@ msgstr "הקובץ גדול מדי ־ גודל הקובץ המרבי הוא עד
104106

105107
#: lmsweb/tools/validators.py:13
106108
msgid "The username is already in use"
107-
msgstr "שם המשתמש כבר נמצא בשימוש"
109+
msgstr "שם המשתמש הזה כבר נמצא בשימוש"
108110

109111
#: lmsweb/tools/validators.py:21
110112
msgid "The email is already in use"
111-
msgstr "האימייל כבר נמצא בשימוש"
113+
msgstr "כתובת הדואר האלקטרוני הזו כבר נמצאת בשימוש"
112114

113115
#: models/solutions.py:52
114116
#, python-format
@@ -280,7 +282,7 @@ msgstr "הזינו סיסמה לצורך שינוי הסיסמה:"
280282

281283
#: templates/reset-password.html:11
282284
msgid "Insert your email for getting link to reset it:"
283-
msgstr "הזינו אימייל לצורך שליחת קישור לאיפוס הסיסמה:"
285+
msgstr "הזינו מייל לצורך שליחת קישור לאיפוס הסיסמה:"
284286

285287
#: templates/reset-password.html:14 templates/signup.html:15
286288
#: templates/user.html:16
@@ -301,7 +303,7 @@ msgstr "הרשמה"
301303

302304
#: templates/signup.html:12
303305
msgid "Insert your email and password for registration:"
304-
msgstr "הזינו אימייל וסיסמה לצורך רישום למערכת:"
306+
msgstr "הזינו מייל וסיסמה לצורך רישום למערכת:"
305307

306308
#: templates/signup.html:17
307309
msgid "Full Name"
@@ -317,11 +319,11 @@ msgstr "שם"
317319

318320
#: templates/status.html:13 templates/user.html:54
319321
msgid "Checked"
320-
msgstr "נבדק/ו"
322+
msgstr "נבדקו"
321323

322324
#: templates/status.html:14
323325
msgid "Solved"
324-
msgstr "נפתר/ו"
326+
msgstr "נפתרו"
325327

326328
#: templates/status.html:15
327329
msgid "Percentage"
@@ -353,7 +355,7 @@ msgstr "העלאת מחברות"
353355

354356
#: templates/upload.html:11
355357
msgid "Drag here the notebook file or click and choose it from your computer."
356-
msgstr "גררו לכאן את קובץ המחברת, או לחצו ובחרו אותה מהמחשב שלכם."
358+
msgstr "גררו לכאן את קובץ המחברת, או לחצו ובחרו אותה מהמחשב שלכם."
357359

358360
#: templates/upload.html:14
359361
msgid "Back to Exercises List"
@@ -409,7 +411,7 @@ msgstr "בודק"
409411

410412
#: templates/user.html:44 templates/view.html:25 templates/view.html:112
411413
msgid "Assessment"
412-
msgstr "הערה מילולית"
414+
msgstr "הערכה מילולית"
413415

414416
#: templates/user.html:54
415417
msgid "Submitted"
@@ -429,7 +431,7 @@ msgstr "פתקית חדשה"
429431

430432
#: templates/user.html:77
431433
msgid "Related Exercise"
432-
msgstr "תרגיל משויך"
434+
msgstr "עבור תרגיל"
433435

434436
#: templates/user.html:86
435437
msgid "Privacy Level"
@@ -441,7 +443,7 @@ msgstr "הוסף פתקית"
441443

442444
#: templates/view.html:6
443445
msgid "Exercise view"
444-
msgstr "שם תרגיל"
446+
msgstr "תצוגת תרגיל"
445447

446448
#: templates/view.html:9
447449
msgid "Your solution had checked!"
@@ -457,7 +459,7 @@ msgstr "התרגיל שלך נבדק ברגעים אלו!"
457459

458460
#: templates/view.html:13
459461
msgid "This solution is not up to date!"
460-
msgstr "פתרון זה אינו פתרון עדכני!"
462+
msgstr "פתרון זה אינו עדכני!"
461463

462464
#: templates/view.html:15
463465
msgid "Your solution hasn't been checked."
@@ -489,11 +491,11 @@ msgstr "בדיקות אוטומטיות"
489491

490492
#: templates/view.html:93
491493
msgid "Error"
492-
msgstr "כישלון חמור"
494+
msgstr "כישלון"
493495

494496
#: templates/view.html:98
495497
msgid "Staff Error"
496-
msgstr "כישלון חמור"
498+
msgstr "כישלון סגל"
497499

498500
#: templates/view.html:134
499501
msgid "General comments"
@@ -505,12 +507,12 @@ msgstr "הערות בודק"
505507

506508
#: templates/view.html:152
507509
msgid "Done Checking"
508-
msgstr "סיום בדיקה"
510+
msgstr "סיים לבדוק"
509511

510512
#: utils/mail.py:25
511513
#, python-format
512514
msgid "Confirmation mail - %(site_name)s"
513-
msgstr "מייל אימות - %(site_name)s"
515+
msgstr "הודעת אימות - %(site_name)s"
514516

515517
#: utils/mail.py:32
516518
#, python-format
@@ -519,12 +521,12 @@ msgid ""
519521
"Your confirmation link is: %(link)s"
520522
msgstr ""
521523
"שלום %(fullname)s,\n"
522-
"לינק האימות שלך למערכת הוא: %(link)s"
524+
"קישור האימות שלך למערכת הוא: %(link)s"
523525

524526
#: utils/mail.py:42
525527
#, python-format
526528
msgid "Reset password mail - %(site_name)s"
527-
msgstr "מייל איפוס סיסמה - %(site_name)s"
529+
msgstr "הודעה על איפוס סיסמה - %(site_name)s"
528530

529531
#: utils/mail.py:49
530532
#, python-format
@@ -533,7 +535,7 @@ msgid ""
533535
"Your reset password link is: %(link)s"
534536
msgstr ""
535537
"שלום %(fullname)s,\n"
536-
"לינק לצורך איפוס הסיסמה שלך הוא: %(link)s"
538+
"הקישור לצורך איפוס הסיסמה שלך הוא: %(link)s"
537539

538540
#: utils/mail.py:58
539541
#, python-format
@@ -543,12 +545,10 @@ msgstr "שינוי סיסמה - %(site_name)s"
543545
#: utils/mail.py:62
544546
#, python-format
545547
msgid ""
546-
"Hello %(fullname)s. Your password in %(site_name)s site has been changed."
547-
"\n"
548+
"Hello %(fullname)s. Your password in %(site_name)s site has been changed.\n"
548549
"If you didn't do it please contact with the site management.\n"
549550
"Mail address: %(site_mail)s"
550551
msgstr ""
551552
"שלום %(fullname)s. הסיסמה שלך באתר %(site_name)s שונתה.\n"
552-
"אם אתה לא עשית את זה צור קשר עם הנהלת האתר.\n"
553-
"כתובת המייל: %(site_mail)s"
554-
553+
"אם לא אתה שינית את הסיסמה, צור קשר עם הנהלת האתר.\n"
554+
"כתובת המייל שלך לפי רישומינו: %(site_mail)s"

lms/lmsweb/views.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,13 +362,21 @@ def main():
362362
return redirect(url_for('exercises_page'))
363363

364364

365-
@webapp.route(routes.STATUS)
365+
@webapp.route(f'{routes.STATUS}/')
366+
def overview_status():
367+
return render_template(
368+
'status.html',
369+
exercises=Solution.status(),
370+
)
371+
372+
373+
@webapp.route(f'/course/<int:course_id>/{routes.STATUS.strip("/")}/')
366374
@managers_only
367375
@login_required
368-
def status():
376+
def status(course_id: int):
369377
return render_template(
370378
'status.html',
371-
exercises=Solution.status(),
379+
exercises=Solution.status(course_id),
372380
)
373381

374382

@@ -420,7 +428,7 @@ def share():
420428
solution_id = int(request.json.get('solutionId', 0))
421429

422430
try:
423-
shared_solution = share_link.get(solution_id)
431+
shared_solution = share_link.get_or_create(solution_id)
424432
except LmsError as e:
425433
error_message, status_code = e.args
426434
return fail(status_code, error_message)
@@ -710,7 +718,7 @@ def shared_solution(shared_url: str, file_id: Optional[int] = None):
710718
if shared_solution is None:
711719
return fail(404, 'The solution does not exist.')
712720

713-
share_link.new(shared_solution)
721+
share_link.new_visit(shared_solution)
714722
solution_id = shared_solution.solution.id
715723
return view(
716724
solution_id=solution_id, file_id=file_id, shared_url=shared_url,

0 commit comments

Comments
 (0)