Merge pull request #1970 from frappe/develop

chore: merge 'develop' into 'main'
This commit is contained in:
Jannat Patel
2026-01-07 14:29:49 +05:30
committed by GitHub
16 changed files with 336 additions and 168 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: setup python
uses: actions/setup-python@v2
uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: setup node
+2 -2
View File
@@ -22,9 +22,9 @@ jobs:
ref: ${{ matrix.branch }}
- name: Setup Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"
python-version: "3.14"
- name: Run script to update POT file
run: |
+2 -2
View File
@@ -35,9 +35,9 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.10'
python-version: '3.14'
- name: Cache pip
uses: actions/cache@v4
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.14'
@@ -19,6 +19,14 @@
showOptions = true
}
"
@focus="
() => {
showOptions = true
if (!filterOptions.data || filterOptions.data.length === 0) {
reload('')
}
}
"
autocomplete="off"
/>
</template>
@@ -152,9 +160,6 @@ const selectedValue = computed({
get: () => query.value || '',
set: (val) => {
query.value = ''
if (val) {
showOptions.value = false
}
val?.value && addValue(val.value)
},
})
@@ -183,7 +188,8 @@ const filterOptions = createResource({
const options = computed(() => {
setFocus()
return filterOptions.data || []
const allOptions = filterOptions.data || []
return allOptions.filter((option) => !values.value?.includes(option.value))
})
function reload(val) {
@@ -25,7 +25,7 @@
:required="true"
/>
<ChildTable
v-model="exercise.test_cases"
v-model="testCases.data"
:label="__('Test Cases')"
:columns="testCaseColumns"
:required="true"
@@ -179,9 +179,7 @@ const testCases = createListResource({
fields: ['input', 'expected_output', 'name'],
cache: ['testCases', props.exerciseID],
parent: 'LMS Programming Exercise',
onSuccess(data: TestCase[]) {
exercise.value.test_cases = data
},
orderBy: 'idx',
})
const fetchTestCases = () => {
@@ -200,6 +198,13 @@ const validateTitle = () => {
}
const saveExercise = (close: () => void) => {
exercise.value.test_cases = testCases.data.map(
(tc: TestCase, index: number) => ({
input: tc.input,
expected_output: tc.expected_output,
idx: index + 1,
})
)
validateTitle()
if (props.exerciseID == 'new') createNewExercise(close)
else updateExercise(close)
+6 -1
View File
@@ -112,7 +112,12 @@
}"
>
<template #body-content>
<FormControl v-model="title" :label="__('Title')" type="text" />
<FormControl
v-model="title"
:label="__('Title')"
type="text"
@keydown.enter="insertQuiz(() => (showForm = false))"
/>
</template>
</Dialog>
</template>
+19 -3
View File
@@ -79,7 +79,10 @@
</div>
<div
v-if="
result.published_on || result.start_date || result.creation
result.published_on ||
result.start_date ||
result.creation ||
result.modified
"
class="ml-auto text-sm text-ink-gray-5"
>
@@ -87,7 +90,8 @@
dayjs(
result.published_on ||
result.start_date ||
result.creation
result.creation ||
result.modified
).format('DD MMM YYYY')
}}
</div>
@@ -164,10 +168,22 @@ const generateSearchResults = () => {
searchResults.value.push(item)
})
})
searchResults.value.sort((a, b) => b.score - a.score)
sortResults()
}
}
const sortResults = () => {
searchResults.value.sort((a, b) => {
const dateA = new Date(
a.published_on || a.start_date || a.creation || a.modified
).getTime()
const dateB = new Date(
b.published_on || b.start_date || b.creation || b.modified
).getTime()
return dateB - dateA
})
}
const navigate = (result: any) => {
if (result.doctype == 'LMS Course') {
router.push({
+27 -7
View File
@@ -17,9 +17,20 @@ def search_sqlite(query: str):
def prepare_search_results(result):
groups = get_grouped_results(result)
out = []
for key in groups:
groups[key] = remove_duplicates(groups[key])
groups[key].sort(key=lambda x: x.get("modified"), reverse=True)
out.append({"title": key, "items": groups[key]})
return out
def get_grouped_results(result):
roles = frappe.get_roles()
groups = {}
for r in result["results"]:
doctype = r["doctype"]
if doctype == "LMS Course" and can_access_course(r, roles):
@@ -31,12 +42,17 @@ def prepare_search_results(result):
elif doctype == "Job Opportunity" and can_access_job(r, roles):
r["author_info"] = get_instructor_info(doctype, r)
groups.setdefault("Job Opportunities", []).append(r)
return groups
out = []
for key in groups:
out.append({"title": key, "items": groups[key]})
return out
def remove_duplicates(items):
seen = set()
unique_items = []
for item in items:
if item["name"] not in seen:
seen.add(item["name"])
unique_items.append(item)
return unique_items
def can_access_course(course, roles):
@@ -73,10 +89,14 @@ def get_instructor_info(doctype, record):
instructors = frappe.get_all(
"Course Instructor", filters={"parenttype": doctype, "parent": record.get("name")}, pluck="instructor"
)
instructor = record.get("author")
if len(instructors):
instructor = instructors[0]
for ins in instructors:
if ins.split("@")[0] in record.get("content"):
instructor = ins
break
if not instructor:
instructor = instructors[0]
return frappe.db.get_value(
"User",
@@ -52,13 +52,17 @@ class TestCourseEvaluator(UnitTestCase):
return first_date
def calculated_last_date_of_schedule(self, first_date):
last_day = add_days(first_date, 56)
last_day = add_days(getdate(), 56)
offset_monday = (0 - last_day.weekday() + 7) % 7 # 0 for Monday
offset_wednesday = (2 - last_day.weekday() + 7) % 7 # 2 for Wednesday
if offset_monday > offset_wednesday and offset_monday < 4:
if offset_monday < offset_wednesday and offset_monday <= 4:
last_day = add_days(last_day, offset_monday)
else:
elif offset_wednesday <= 4:
last_day = add_days(last_day, offset_wednesday)
else:
last_day = add_days(last_day, min(offset_monday, offset_wednesday) + 7)
return last_day
def test_unavailability_dates(self):
+53 -23
View File
@@ -8,6 +8,7 @@ from frappe import _
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_result
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
from frappe.desk.notifications import extract_mentions
from frappe.pulse.utils import get_frappe_version
from frappe.rate_limiter import rate_limit
from frappe.utils import (
add_months,
@@ -526,38 +527,17 @@ def get_lesson_count(course):
@rate_limit(limit=500, seconds=60 * 60)
def get_chart_data(
chart_name,
timespan="Select Date Range",
timegrain="Daily",
from_date=None,
to_date=None,
):
if not from_date:
from_date = add_months(getdate(), -1)
if not to_date:
to_date = getdate()
from_date = get_datetime(from_date).strftime("%Y-%m-%d")
to_date = get_datetime(to_date)
from_date, to_date = get_chart_date_range(from_date, to_date)
chart = frappe.get_doc("Dashboard Chart", chart_name)
doctype = chart.document_type
datefield = chart.based_on
value_field = chart.value_based_on or "1"
filters = [([chart.document_type, "docstatus", "<", 2])]
filters = filters + json.loads(chart.filters_json)
filters.append([doctype, datefield, ">=", from_date])
filters.append([doctype, datefield, "<=", to_date])
data = frappe.db.get_all(
doctype,
fields=[datefield, {"SUM": value_field}, {"COUNT": "*"}],
filters=filters,
group_by=datefield,
order_by=datefield,
as_list=True,
)
data = get_chart_details(doctype, datefield, value_field, chart, from_date, to_date)
result = get_result(data, timegrain, from_date, to_date, chart.chart_type)
data = []
for row in result:
@@ -570,6 +550,56 @@ def get_chart_data(
return data
def get_chart_date_range(from_date, to_date):
if not from_date:
from_date = add_months(getdate(), -1)
if not to_date:
to_date = getdate()
from_date = get_datetime(from_date).strftime("%Y-%m-%d")
to_date = get_datetime(to_date)
return from_date, to_date
def get_chart_filters(doctype, chart, datefield, from_date, to_date):
version = get_frappe_version()
if version.startswith("16."):
filters = [([chart.document_type, "docstatus", "<", 2])]
filters = filters + json.loads(chart.filters_json)
filters.append([doctype, datefield, ">=", from_date])
filters.append([doctype, datefield, "<=", to_date])
else:
filters = [([chart.document_type, "docstatus", "<", 2, False])]
filters = filters + json.loads(chart.filters_json)
filters.append([doctype, datefield, ">=", from_date, False])
filters.append([doctype, datefield, "<=", to_date, False])
return filters
def get_chart_details(doctype, datefield, value_field, chart, from_date, to_date):
filters = get_chart_filters(doctype, chart, datefield, from_date, to_date)
version = get_frappe_version()
if version.startswith("16."):
return frappe.db.get_all(
doctype,
fields=[datefield, {"SUM": value_field}, {"COUNT": "*"}],
filters=filters,
group_by=datefield,
order_by=datefield,
as_list=True,
)
else:
return frappe.db.get_all(
doctype,
fields=[f"{datefield} as _unit", f"SUM({value_field})", "COUNT(*)"],
filters=filters,
group_by="_unit",
order_by="_unit asc",
as_list=True,
)
@frappe.whitelist(allow_guest=True)
@rate_limit(limit=500, seconds=60 * 60)
def get_course_completion_data():
+3 -3
View File
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-12-19 16:05+0000\n"
"PO-Revision-Date: 2025-12-29 11:09\n"
"PO-Revision-Date: 2026-01-05 13:42\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Persian\n"
"MIME-Version: 1.0\n"
@@ -1206,7 +1206,7 @@ msgstr "اینجا کلیک کنید"
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
#: lms/lms/doctype/zoom_settings/zoom_settings.json
msgid "Client ID"
msgstr "شناسه مشتری"
msgstr "شناسه کلاینت"
#. Label of the client_secret (Password) field in DocType 'LMS Zoom Settings'
#. Label of the client_secret (Password) field in DocType 'Zoom Settings'
@@ -1214,7 +1214,7 @@ msgstr "شناسه مشتری"
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
#: lms/lms/doctype/zoom_settings/zoom_settings.json
msgid "Client Secret"
msgstr "راز مشتری"
msgstr "سیکرت کلاینت"
#: frontend/src/components/Settings/Categories.vue:27
msgid "Close"
+3 -3
View File
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-12-19 16:05+0000\n"
"PO-Revision-Date: 2025-12-23 23:25\n"
"PO-Revision-Date: 2026-01-06 14:31\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Hungarian\n"
"MIME-Version: 1.0\n"
@@ -4741,7 +4741,7 @@ msgstr "Kimenet"
#: frontend/src/components/Settings/BadgeForm.vue:216
#: lms/lms/doctype/lms_badge/lms_badge.js:37
msgid "Owner"
msgstr ""
msgstr "Tulajdonos"
#. Label of the pan (Data) field in DocType 'LMS Payment'
#: frontend/src/components/Settings/Transactions/TransactionDetails.vue:108
@@ -5969,7 +5969,7 @@ msgstr ""
#: frontend/src/components/Controls/ColorSwatches.vue:13
msgid "Set Color"
msgstr ""
msgstr "Szín Beállítása"
#: lms/templates/emails/community_course_membership.html:1
msgid "Set your Password"
+64 -64
View File
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-12-19 16:05+0000\n"
"PO-Revision-Date: 2025-12-23 23:25\n"
"PO-Revision-Date: 2026-01-05 13:42\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Dutch\n"
"MIME-Version: 1.0\n"
@@ -116,7 +116,7 @@ msgstr ""
#: frontend/src/components/Settings/ZoomSettings.vue:192
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
msgid "Account Name"
msgstr ""
msgstr "Accountnaam"
#: frontend/src/pages/ProfileAbout.vue:34
msgid "Achievements"
@@ -296,7 +296,7 @@ msgstr "Beheerder"
#. Name of a role
#: frontend/src/pages/Batches.vue:319 lms/lms/doctype/lms_badge/lms_badge.json
msgid "All"
msgstr ""
msgstr "Allemaal"
#: frontend/src/pages/Batches.vue:68
msgid "All Batches"
@@ -357,7 +357,7 @@ msgstr ""
#: lms/lms/doctype/lms_course/lms_course.json
#: lms/lms/doctype/lms_payment/lms_payment.json
msgid "Amount"
msgstr ""
msgstr "Bedrag"
#. Label of the amount_usd (Currency) field in DocType 'LMS Batch'
#. Label of the amount_usd (Currency) field in DocType 'LMS Course'
@@ -936,7 +936,7 @@ msgstr ""
#: frontend/src/components/UpcomingEvaluations.vue:62
#: frontend/src/components/UpcomingEvaluations.vue:184
msgid "Cancel"
msgstr ""
msgstr "Annuleren"
#: frontend/src/components/UpcomingEvaluations.vue:178
msgid "Cancel this evaluation?"
@@ -968,7 +968,7 @@ msgstr ""
#: lms/lms/doctype/lms_category/lms_category.json
#: lms/lms/doctype/lms_course/lms_course.json lms/templates/signup-form.html:22
msgid "Category"
msgstr ""
msgstr "Categorie"
#: frontend/src/components/Settings/Categories.vue:39
msgid "Category Name"
@@ -1076,7 +1076,7 @@ msgstr ""
#: lms/templates/assignment.html:13
msgid "Change"
msgstr ""
msgstr "Verandering"
#: frontend/src/components/Assignment.vue:351
msgid "Changes saved successfully"
@@ -1218,7 +1218,7 @@ msgstr ""
#: frontend/src/components/Settings/Categories.vue:27
msgid "Close"
msgstr ""
msgstr "Dichtbij"
#. Option for the 'Status' (Select) field in DocType 'Job Opportunity'
#. Option in a Select field in the job-opportunity Web Form
@@ -1249,7 +1249,7 @@ msgstr ""
#: frontend/src/components/Sidebar/AppSidebar.vue:155
msgid "Collapse"
msgstr ""
msgstr "Ineenstorting"
#. Label of the college (Data) field in DocType 'User'
#: lms/fixtures/custom_field.json
@@ -1264,7 +1264,7 @@ msgstr ""
#: lms/lms/doctype/lms_lesson_note/lms_lesson_note.json
#: lms/lms/doctype/lms_timetable_legend/lms_timetable_legend.json
msgid "Color"
msgstr ""
msgstr "Kleur"
#: frontend/src/pages/BatchForm.vue:306 frontend/src/pages/CourseForm.vue:312
msgid "Comma separated keywords for SEO"
@@ -1277,7 +1277,7 @@ msgstr ""
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
#: lms/lms/doctype/lms_mentor_request/lms_mentor_request.json
msgid "Comments"
msgstr ""
msgstr "Reacties"
#: frontend/src/components/Assignment.vue:148
msgid "Comments by Evaluator"
@@ -1373,7 +1373,7 @@ msgstr ""
#: lms/lms/doctype/lms_certificate_request/lms_certificate_request.json
#: lms/lms/widgets/CourseCard.html:78
msgid "Completed"
msgstr ""
msgstr "Voltooid"
#. Label of the enable_certification (Check) field in DocType 'LMS Course'
#: frontend/src/pages/CourseForm.vue:249
@@ -1778,7 +1778,7 @@ msgstr ""
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:32
#: frontend/src/pages/Quizzes.vue:10
msgid "Create"
msgstr ""
msgstr "Creëren"
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.js:7
msgid "Create Certificate"
@@ -1791,7 +1791,7 @@ msgstr ""
#: frontend/src/components/Controls/Link.vue:38
#: frontend/src/components/Controls/MultiSelect.vue:68
msgid "Create New"
msgstr ""
msgstr "Maak nieuw"
#: frontend/src/pages/Programs/ProgramForm.vue:12
msgid "Create Program"
@@ -1866,7 +1866,7 @@ msgstr ""
#: lms/lms/doctype/lms_course/lms_course.json
#: lms/lms/doctype/lms_payment/lms_payment.json
msgid "Currency"
msgstr ""
msgstr "Valuta"
#. Label of the current_lesson (Link) field in DocType 'LMS Enrollment'
#: lms/lms/doctype/lms_enrollment/lms_enrollment.json
@@ -1929,7 +1929,7 @@ msgstr ""
#: lms/lms/doctype/lms_live_class/lms_live_class.json
#: lms/lms/doctype/scheduled_flow/scheduled_flow.json
msgid "Date"
msgstr ""
msgstr "Datum"
#: frontend/src/pages/BatchForm.vue:76
msgid "Date and Time"
@@ -1986,7 +1986,7 @@ msgstr ""
#: frontend/src/pages/Programs/ProgramForm.vue:230
#: frontend/src/pages/Programs/ProgramForm.vue:567
msgid "Delete"
msgstr ""
msgstr "Verwijder"
#: frontend/src/components/CourseOutline.vue:67
msgid "Delete Chapter"
@@ -2048,7 +2048,7 @@ msgstr ""
#: lms/lms/doctype/lms_live_class/lms_live_class.json
#: lms/lms/doctype/work_experience/work_experience.json
msgid "Description"
msgstr ""
msgstr "Beschrijving"
#: frontend/src/components/Sidebar/Apps.vue:50
msgid "Desk"
@@ -2084,7 +2084,7 @@ msgstr ""
#: frontend/src/components/Settings/PaymentGateways.vue:55
#: frontend/src/components/Settings/ZoomSettings.vue:66
msgid "Disabled"
msgstr ""
msgstr "Uitgeschakeld"
#: frontend/src/components/DiscussionReplies.vue:57
#: lms/lms/widgets/NoPreviewModal.html:25
@@ -2134,7 +2134,7 @@ msgstr ""
#: frontend/src/components/Settings/Coupons/CouponItems.vue:8
msgid "Document Type"
msgstr ""
msgstr "Soort document"
#: lms/templates/emails/payment_reminder.html:11
msgid "Dont miss this opportunity to enhance your skills. Click below to complete your enrollment"
@@ -2157,7 +2157,7 @@ msgstr ""
#: lms/lms/doctype/lms_live_class/lms_live_class.json
#: lms/lms/doctype/lms_live_class_participant/lms_live_class_participant.json
msgid "Duration"
msgstr ""
msgstr "Looptijd"
#. Label of the duration (Data) field in DocType 'LMS Quiz'
#: frontend/src/pages/QuizForm.vue:67 lms/lms/doctype/lms_quiz/lms_quiz.json
@@ -2176,7 +2176,7 @@ msgstr ""
#: frontend/src/pages/JobDetail.vue:45 frontend/src/pages/Lesson.vue:42
#: frontend/src/pages/Lesson.vue:178 frontend/src/pages/Profile.vue:44
msgid "Edit"
msgstr ""
msgstr "Bewerk"
#: frontend/src/components/Modals/AssignmentForm.vue:14
msgid "Edit Assignment"
@@ -2246,7 +2246,7 @@ msgstr ""
#: frontend/src/components/Settings/Members.vue:103
#: frontend/src/pages/JobApplications.vue:305 lms/templates/signup-form.html:10
msgid "Email"
msgstr ""
msgstr "E-mail"
#: frontend/src/components/Modals/Event.vue:16
msgid "Email ID"
@@ -2327,7 +2327,7 @@ msgstr ""
#: lms/lms/doctype/lms_coupon/lms_coupon.json
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
msgid "Enabled"
msgstr ""
msgstr "Ingeschakeld"
#: frontend/src/components/Modals/BulkCertificates.vue:53
msgid "Enabling this will publish the certificate on the certified participants page."
@@ -2336,7 +2336,7 @@ msgstr ""
#. Label of the end_date (Date) field in DocType 'LMS Batch'
#: lms/lms/doctype/lms_batch/lms_batch.json
msgid "End Date"
msgstr ""
msgstr "Einddatum"
#. Label of the end_date (Date) field in DocType 'Education Detail'
#: lms/lms/doctype/education_detail/education_detail.json
@@ -2585,7 +2585,7 @@ msgstr ""
#: frontend/src/components/Sidebar/AppSidebar.vue:155
msgid "Expand"
msgstr ""
msgstr "Uitbreiden"
#. Label of the expected_output (Data) field in DocType 'LMS Test Case'
#. Label of the expected_output (Data) field in DocType 'LMS Test Case
@@ -2654,7 +2654,7 @@ msgstr ""
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Failed"
msgstr ""
msgstr "Gefaald"
#: frontend/src/components/Settings/BadgeAssignmentForm.vue:136
msgid "Failed to create badge assignment: "
@@ -2738,7 +2738,7 @@ msgstr ""
#: frontend/src/components/Modals/EditProfile.vue:72
#: frontend/src/components/Settings/Members.vue:110
msgid "First Name"
msgstr ""
msgstr "Voornaam"
#. Option for the 'Time Preference' (Select) field in DocType 'User'
#: lms/fixtures/custom_field.json
@@ -2798,12 +2798,12 @@ msgstr ""
#: frontend/src/pages/ProfileEvaluator.vue:106
#: lms/lms/doctype/course_evaluator/course_evaluator.json
msgid "From"
msgstr ""
msgstr "Van"
#. Label of the from_date (Date) field in DocType 'Work Experience'
#: lms/lms/doctype/work_experience/work_experience.json
msgid "From Date"
msgstr ""
msgstr "Van Datum"
#. Label of the full_name (Data) field in DocType 'Course Evaluator'
#. Label of the full_name (Data) field in DocType 'LMS Program Member'
@@ -2812,7 +2812,7 @@ msgstr ""
#: lms/lms/doctype/lms_program_member/lms_program_member.json
#: lms/templates/signup-form.html:5
msgid "Full Name"
msgstr ""
msgstr "Volledige naam"
#. Option for the 'Type' (Select) field in DocType 'Job Opportunity'
#. Option in a Select field in the job-opportunity Web Form
@@ -3047,7 +3047,7 @@ msgstr ""
#: frontend/src/components/Modals/PageModal.vue:28
#: lms/lms/doctype/lms_sidebar_item/lms_sidebar_item.json
msgid "Icon"
msgstr ""
msgstr "Icoon"
#. Label of the user_category (Check) field in DocType 'LMS Settings'
#: lms/lms/doctype/lms_settings/lms_settings.json
@@ -3130,7 +3130,7 @@ msgstr ""
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json
#: lms/lms/doctype/lms_course/lms_course.json
msgid "In Progress"
msgstr ""
msgstr "Bezig"
#. Label of the include_in_preview (Check) field in DocType 'Course Lesson'
#: lms/lms/doctype/course_lesson/course_lesson.json
@@ -3690,7 +3690,7 @@ msgstr ""
#: frontend/src/components/Modals/EditProfile.vue:76
msgid "Last Name"
msgstr ""
msgstr "Achternaam"
#. Label of the launch_file (Code) field in DocType 'Course Chapter'
#: lms/lms/doctype/course_chapter/course_chapter.json
@@ -3834,7 +3834,7 @@ msgstr ""
#: frontend/src/pages/QuizSubmissionList.vue:39
#: frontend/src/pages/Quizzes.vue:94
msgid "Load More"
msgstr ""
msgstr "Meer laden"
#. Option for the 'Auto Recording' (Select) field in DocType 'LMS Live Class'
#: lms/lms/doctype/lms_live_class/lms_live_class.json
@@ -4184,7 +4184,7 @@ msgstr ""
#: frontend/src/components/ContactUsEmail.vue:19
#: frontend/src/pages/JobApplications.vue:137
msgid "Message"
msgstr ""
msgstr "Bericht"
#: frontend/src/pages/JobApplications.vue:261
msgid "Message is required"
@@ -4317,7 +4317,7 @@ msgstr ""
#: frontend/src/components/Modals/EmailTemplateModal.vue:24
msgid "Name"
msgstr ""
msgstr "Naam"
#. Option for the 'Event' (Select) field in DocType 'LMS Badge'
#: frontend/src/components/Settings/BadgeAssignments.vue:21
@@ -4333,7 +4333,7 @@ msgstr ""
#: frontend/src/pages/Programs/Programs.vue:10
#: lms/lms/doctype/lms_badge/lms_badge.json
msgid "New"
msgstr ""
msgstr "Nieuw"
#: frontend/src/pages/Batches.vue:10 lms/www/lms.py:150
msgid "New Batch"
@@ -4499,7 +4499,7 @@ msgstr ""
#: frontend/src/components/Controls/MultiSelect.vue:59
#: frontend/src/pages/Search/Search.vue:47
msgid "No results found"
msgstr ""
msgstr "No results found"
#: frontend/src/components/Modals/EvaluationModal.vue:59
msgid "No slots available for the selected course."
@@ -4523,7 +4523,7 @@ msgstr ""
#: lms/lms/user.py:29
msgid "Not Allowed"
msgstr ""
msgstr "Niet Toegestaan"
#. Option for the 'Status' (Select) field in DocType 'LMS Assignment
#. Submission'
@@ -4555,17 +4555,17 @@ msgstr ""
#: frontend/src/pages/Programs/ProgramForm.vue:16
#: frontend/src/pages/QuizForm.vue:8 frontend/src/pages/QuizSubmission.vue:9
msgid "Not Saved"
msgstr ""
msgstr "Niet opgeslagen"
#. Label of the note (Text Editor) field in DocType 'LMS Lesson Note'
#: lms/lms/doctype/lms_lesson_note/lms_lesson_note.json
msgid "Note"
msgstr ""
msgstr "Opmerking"
#: frontend/src/pages/Lesson.vue:405 frontend/src/pages/Lesson.vue:886
#: frontend/src/pages/Lesson.vue:897
msgid "Notes"
msgstr ""
msgstr "Opmerkingen"
#: frontend/src/pages/Notifications.vue:53
msgid "Nothing to see here."
@@ -4939,7 +4939,7 @@ msgstr ""
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json
#: lms/lms/doctype/lms_mentor_request/lms_mentor_request.json
msgid "Pending"
msgstr ""
msgstr "In afwachting van"
#. Option for the 'Discount Type' (Select) field in DocType 'LMS Coupon'
#. Label of the percentage (Int) field in DocType 'LMS Quiz Submission'
@@ -5608,13 +5608,13 @@ msgstr ""
#. Label of the reference_doctype (Link) field in DocType 'LMS Badge'
#: lms/lms/doctype/lms_badge/lms_badge.json
msgid "Reference Document Type"
msgstr ""
msgstr "Referentie Document Type"
#. Label of the reference_name (Dynamic Link) field in DocType 'LMS Coupon
#. Item'
#: lms/lms/doctype/lms_coupon_item/lms_coupon_item.json
msgid "Reference Name"
msgstr ""
msgstr "Referentienaam"
#: lms/templates/emails/community_course_membership.html:17
msgid "Regards"
@@ -5707,7 +5707,7 @@ msgstr ""
#. Label of the role (Select) field in DocType 'LMS Enrollment'
#: lms/lms/doctype/lms_enrollment/lms_enrollment.json
msgid "Role"
msgstr ""
msgstr "Rol"
#. Label of the role (Select) field in DocType 'User'
#: lms/fixtures/custom_field.json
@@ -5815,7 +5815,7 @@ msgstr ""
#: frontend/src/pages/Quizzes.vue:105
#: lms/job/web_form/job_opportunity/job_opportunity.json
msgid "Save"
msgstr ""
msgstr "bewaren"
#. Label of the schedule (Table) field in DocType 'Course Evaluator'
#: lms/lms/doctype/course_evaluator/course_evaluator.json
@@ -5856,7 +5856,7 @@ msgstr ""
#: frontend/src/pages/Jobs.vue:44 frontend/src/pages/Search/Search.vue:5
#: frontend/src/pages/Search/Search.vue:228
msgid "Search"
msgstr ""
msgstr "Zoek"
#: frontend/src/components/Modals/CourseProgressSummary.vue:17
#: frontend/src/components/Modals/VideoStatistics.vue:20
@@ -5939,7 +5939,7 @@ msgstr ""
#: frontend/src/components/ContactUsEmail.vue:33
#: frontend/src/pages/JobApplications.vue:115
msgid "Send"
msgstr ""
msgstr "Verstuur"
#: lms/lms/doctype/lms_batch_enrollment/lms_batch_enrollment.js:7
msgid "Send Confirmation Email"
@@ -5990,7 +5990,7 @@ msgstr ""
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:19
#: frontend/src/pages/QuizForm.vue:86
msgid "Settings"
msgstr ""
msgstr "instellingen"
#: frontend/src/pages/ProfileAbout.vue:81
msgid "Share on"
@@ -6135,7 +6135,7 @@ msgstr ""
#: lms/lms/doctype/lms_source/lms_source.json
#: lms/lms/doctype/lms_video_watch_duration/lms_video_watch_duration.json
msgid "Source"
msgstr ""
msgstr "Bron"
#. Option for the 'Member Type' (Select) field in DocType 'LMS Enrollment'
#: lms/lms/doctype/lms_enrollment/lms_enrollment.json
@@ -6153,7 +6153,7 @@ msgstr ""
#: lms/lms/doctype/education_detail/education_detail.json
#: lms/lms/doctype/lms_batch/lms_batch.json
msgid "Start Date"
msgstr ""
msgstr "Startdatum"
#: lms/templates/emails/batch_start_reminder.html:13
msgid "Start Date:"
@@ -6280,7 +6280,7 @@ msgstr ""
#: frontend/src/components/Modals/EmailTemplateModal.vue:31
#: frontend/src/pages/JobApplications.vue:126
msgid "Subject"
msgstr ""
msgstr "Onderwerp"
#: frontend/src/components/Modals/AnnouncementModal.vue:94
#: frontend/src/pages/JobApplications.vue:258
@@ -6660,7 +6660,7 @@ msgstr ""
#: frontend/src/components/Quiz.vue:58
#: lms/lms/doctype/lms_live_class/lms_live_class.json
msgid "Time"
msgstr ""
msgstr "Tijd"
#. Label of the time (Select) field in DocType 'User'
#: lms/fixtures/custom_field.json
@@ -6768,7 +6768,7 @@ msgstr ""
#: lms/lms/doctype/lms_timetable_template/lms_timetable_template.json
#: lms/lms/doctype/work_experience/work_experience.json
msgid "Title"
msgstr ""
msgstr "Titel"
#: frontend/src/components/Modals/ChapterModal.vue:172
msgid "Title is required"
@@ -6778,12 +6778,12 @@ msgstr ""
#: frontend/src/pages/ProfileEvaluator.vue:120
#: lms/lms/doctype/course_evaluator/course_evaluator.json
msgid "To"
msgstr ""
msgstr "Naar"
#. Label of the to_date (Date) field in DocType 'Work Experience'
#: lms/lms/doctype/work_experience/work_experience.json
msgid "To Date"
msgstr ""
msgstr "Tot Datum"
#: lms/lms/utils.py:1553
msgid "To join this batch, please contact the Administrator."
@@ -6795,7 +6795,7 @@ msgstr ""
#: frontend/src/pages/Billing.vue:54
msgid "Total"
msgstr ""
msgstr "Totaal"
#. Label of the total_marks (Int) field in DocType 'LMS Quiz'
#: frontend/src/pages/QuizForm.vue:73 frontend/src/pages/Quizzes.vue:245
@@ -6952,7 +6952,7 @@ msgstr ""
#: frontend/src/components/Settings/BrandSettings.vue:24
#: frontend/src/components/Settings/SettingDetails.vue:23
msgid "Update"
msgstr ""
msgstr "Bijwerken"
#: lms/templates/emails/community_course_membership.html:11
msgid "Update Password"
@@ -6961,7 +6961,7 @@ msgstr ""
#: frontend/src/components/Controls/Uploader.vue:20
#: frontend/src/pages/BatchForm.vue:227 frontend/src/pages/CourseForm.vue:100
msgid "Upload"
msgstr ""
msgstr "Uploaden"
#: frontend/src/components/Assignment.vue:84
msgid "Upload File"
@@ -6992,7 +6992,7 @@ msgstr ""
#: lms/job/doctype/lms_job_application/lms_job_application.json
#: lms/lms/doctype/lms_course_interest/lms_course_interest.json
msgid "User"
msgstr ""
msgstr "Gebruiker"
#. Label of the user_category (Select) field in DocType 'User'
#: lms/fixtures/custom_field.json lms/templates/signup-form.html:17
@@ -7033,7 +7033,7 @@ msgstr ""
#. Label of a shortcut in the LMS Workspace
#: lms/lms/workspace/lms/lms.json
msgid "Users"
msgstr ""
msgstr "Gebruikers"
#. Label of the answer (Small Text) field in DocType 'LMS Quiz Result'
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -7047,7 +7047,7 @@ msgstr ""
#. Label of the value (Rating) field in DocType 'LMS Batch Feedback'
#: lms/lms/doctype/lms_batch_feedback/lms_batch_feedback.json
msgid "Value"
msgstr ""
msgstr "Waarde"
#. Option for the 'Event' (Select) field in DocType 'LMS Badge'
#: lms/lms/doctype/lms_badge/lms_badge.json
+17 -17
View File
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-12-19 16:05+0000\n"
"PO-Revision-Date: 2025-12-24 23:25\n"
"PO-Revision-Date: 2026-01-04 12:55\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Russian\n"
"MIME-Version: 1.0\n"
@@ -664,7 +664,7 @@ msgstr "Доступность успешно обновлена"
#: frontend/src/components/Modals/EvaluationModal.vue:26
msgid "Available Slots"
msgstr ""
msgstr "Доступные слоты"
#: frontend/src/components/BatchFeedback.vue:43
msgid "Average Feedback Received"
@@ -2063,7 +2063,7 @@ msgstr "Детали"
#. Label of the disable_pwa (Check) field in DocType 'LMS Settings'
#: lms/lms/doctype/lms_settings/lms_settings.json
msgid "Disable PWA"
msgstr ""
msgstr "Отключить PWA"
#: frontend/src/pages/CourseForm.vue:174
msgid "Disable Self Enrollment"
@@ -2887,7 +2887,7 @@ msgstr "Установите приложение на ваш iPhone для уд
#: frontend/src/components/Modals/EditProfile.vue:84
msgid "GitHub ID"
msgstr ""
msgstr "Github ID"
#. Label of the github (Data) field in DocType 'User'
#: lms/fixtures/custom_field.json
@@ -3387,7 +3387,7 @@ msgstr "Присоединился в"
#: frontend/src/components/CommandPalette/CommandPalette.vue:132
#: frontend/src/components/CommandPalette/CommandPalette.vue:229
msgid "Jump to"
msgstr ""
msgstr "Перейти к"
#: frontend/src/pages/Home/Streak.vue:18
msgid "Keep going,"
@@ -4503,7 +4503,7 @@ msgstr "Результаты не найдены"
#: frontend/src/components/Modals/EvaluationModal.vue:59
msgid "No slots available for the selected course."
msgstr ""
msgstr "На выбранный курс нет свободных мест."
#: frontend/src/components/Modals/VideoStatistics.vue:86
msgid "No statistics available for this video."
@@ -4665,7 +4665,7 @@ msgstr "Откройте "
#: frontend/src/components/UserAvatar.vue:11 frontend/src/pages/Profile.vue:61
#: lms/fixtures/custom_field.json
msgid "Open to Opportunities"
msgstr ""
msgstr "Открыт для новых возможностей"
#. Label of the option (Data) field in DocType 'LMS Option'
#: frontend/src/components/Modals/Question.vue:70
@@ -5077,7 +5077,7 @@ msgstr "Пожалуйста, войдите в систему, чтобы за
#: frontend/src/pages/Batch.vue:158
msgid "Please make sure to schedule your evaluation before this date."
msgstr ""
msgstr "Пожалуйста, запишитесь на обследование до указанной даты."
#: lms/lms/notification/certificate_request_reminder/certificate_request_reminder.html:7
#: lms/templates/emails/certificate_request_notification.html:7
@@ -5114,7 +5114,7 @@ msgstr "Пожалуйста, выберите тест"
#: frontend/src/components/Modals/EvaluationModal.vue:109
msgid "Please select a slot for your evaluation."
msgstr ""
msgstr "Пожалуйста, выберите время для прохождения оценки."
#: frontend/src/components/Modals/LiveClassModal.vue:192
msgid "Please select a time."
@@ -5214,7 +5214,7 @@ msgstr "Предпочитаемое местоположение"
#: frontend/src/pages/Search/Search.vue:41
msgid "Press enter to search"
msgstr ""
msgstr "Нажмите enter для поиска"
#. Label of the prevent_skipping_videos (Check) field in DocType 'LMS Settings'
#: lms/lms/doctype/lms_settings/lms_settings.json
@@ -5832,7 +5832,7 @@ msgstr "Запланируйте оценку, чтобы получить се
#: frontend/src/components/Modals/EvaluationModal.vue:5
msgid "Schedule your evaluation"
msgstr ""
msgstr "Запланируйте свою оценку"
#. Name of a DocType
#: lms/lms/doctype/scheduled_flow/scheduled_flow.json
@@ -6048,7 +6048,7 @@ msgstr "Показать онлайн урок"
#: frontend/src/components/Modals/EditProfile.vue:61
msgid "Show recruiters and others that you are open to work."
msgstr ""
msgstr "Покажите рекрутерам и другим заинтересованным сторонам, что вы открыты для работы."
#. Label of the shuffle_questions (Check) field in DocType 'LMS Quiz'
#: frontend/src/pages/QuizForm.vue:105 lms/lms/doctype/lms_quiz/lms_quiz.json
@@ -6501,7 +6501,7 @@ msgstr "Оценщик этого курса недоступен от {0} до
#: frontend/src/pages/Batch.vue:151
msgid "The last day to schedule your evaluations is "
msgstr ""
msgstr "Последний день, когда можно назначить оценки "
#: lms/lms/utils.py:2083
msgid "The lesson does not exist."
@@ -6840,7 +6840,7 @@ msgstr "Twitter"
#: frontend/src/components/Modals/EditProfile.vue:87
#: lms/fixtures/custom_field.json
msgid "Twitter ID"
msgstr ""
msgstr "Twitter ID"
#. Label of the type (Select) field in DocType 'Job Opportunity'
#. Label of a field in the job-opportunity Web Form
@@ -7394,7 +7394,7 @@ msgstr "Чтобы назначать значки пользователям,
#: lms/lms/doctype/lms_course_review/lms_course_review.py:18
msgid "You must be enrolled in the course to submit a review"
msgstr ""
msgstr "Для того чтобы оставить отзыв, вы должны быть зачислены на курс"
#: lms/lms/doctype/lms_enrollment/lms_enrollment.py:47
msgid "You need to complete the payment for this course before enrolling."
@@ -7620,11 +7620,11 @@ msgstr "Интерактивное обучение"
#: frontend/src/pages/Search/Search.vue:38
msgid "match"
msgstr ""
msgstr "матч"
#: frontend/src/pages/Search/Search.vue:38
msgid "matches"
msgstr ""
msgstr "матчи"
#: frontend/src/pages/Programs/Programs.vue:42
#: frontend/src/pages/Programs/StudentPrograms.vue:36
+112 -30
View File
@@ -2,7 +2,7 @@ from contextlib import suppress
import frappe
from frappe.search.sqlite_search import SQLiteSearch, SQLiteSearchIndexMissingError
from frappe.utils import nowdate
from frappe.utils import get_datetime, getdate, nowdate
class LearningSearch(SQLiteSearch):
@@ -17,6 +17,8 @@ class LearningSearch(SQLiteSearch):
"status",
"company_name",
"creation",
"parent",
"parenttype",
],
"tokenizer": "unicode61 remove_diacritics 2 tokenchars '-_'",
}
@@ -60,38 +62,66 @@ class LearningSearch(SQLiteSearch):
{"modified": "creation"},
],
},
"Course Instructor": {
"fields": [
"name",
{"title": "instructor"},
{"content": "instructor"},
"parent",
"parenttype",
"modified",
]
},
}
COURSE_FIELDS = [
"name",
"title",
"description",
"short_introduction",
"category",
"published",
"published_on",
"creation",
"modified",
"owner",
]
BATCH_FIELDS = [
"name",
"title",
"description",
"batch_details",
"category",
"start_date",
"creation",
"modified",
"owner",
"published",
]
JOB_FIELDS = [
"name",
"job_title",
"company_name",
"description",
"creation",
"modified",
"owner",
]
INSTRUCTOR_FIELDS = [
"name",
"instructor",
"parent",
"parenttype",
]
DOCTYPE_FIELDS = {
"LMS Course": [
"name",
"title",
"description",
"short_introduction",
"category",
"creation",
"modified",
"owner",
],
"LMS Batch": [
"name",
"title",
"description",
"batch_details",
"category",
"creation",
"modified",
"owner",
],
"Job Opportunity": [
"name",
"job_title",
"company_name",
"description",
"creation",
"modified",
"owner",
],
"LMS Course": COURSE_FIELDS,
"LMS Batch": BATCH_FIELDS,
"Job Opportunity": JOB_FIELDS,
"Course Instructor": INSTRUCTOR_FIELDS,
}
def build_index(self):
@@ -103,6 +133,58 @@ class LearningSearch(SQLiteSearch):
def get_search_filters(self):
return {}
def prepare_document(self, doc):
document = super().prepare_document(doc)
if not document:
return None
if doc.doctype == "Course Instructor":
document = self.get_instructor_details(doc, document)
else:
if not document.get("modified"):
self.set_modified_date(doc, doc.doctype, document)
return document
def get_instructor_details(self, doc, document):
instructor = frappe.db.get_value("User", doc.instructor, "full_name")
fields = self.COURSE_FIELDS if doc.parenttype == "LMS Course" else self.BATCH_FIELDS
details = frappe.db.get_value(doc.parenttype, doc.parent, fields, as_dict=True)
if details:
document["doctype"] = doc.parenttype
document["name"] = doc.parent
document["title"] = self._process_content(details.title)
document["published"] = details.get("published", 0)
document["content"] = self._process_content(
f"Instructor: {instructor}\n{details.description}\n{doc.instructor}"
)
self.set_modified_date(details, doc.parenttype, document)
if doc.parenttype == "LMS Course":
document["published_on"] = details.get("published_on")
elif doc.parenttype == "LMS Batch":
document["start_date"] = details.get("start_date")
return document
def set_modified_date(self, details, doctype, document):
modified_value = None
if doctype == "LMS Course":
modified_value = details.get("published_on")
elif doctype == "LMS Batch":
modified_value = details.get("start_date")
if not modified_value:
modified_value = frappe.db.get_value(doctype, details.name, "creation")
modified_value = get_datetime(modified_value)
if doctype == "LMS Course":
document["published_on"] = getdate(modified_value)
elif doctype == "LMS Batch":
document["start_date"] = getdate(modified_value)
document["modified"] = modified_value.timestamp()
@SQLiteSearch.scoring_function
def get_doctype_boost(self, row, query, query_words):
doctype = row["doctype"]