Merge branch 'develop' into fix/image-upload

This commit is contained in:
Joedeep Singh
2025-07-04 18:57:03 +05:30
committed by GitHub
13 changed files with 375 additions and 257 deletions

View File

@@ -23,8 +23,8 @@ describe("Batch Creation", () => {
const randomEmail = `testuser_${dateNow}@example.com`; const randomEmail = `testuser_${dateNow}@example.com`;
const randomName = `Test User ${dateNow}`; const randomName = `Test User ${dateNow}`;
cy.get("input[placeholder='Email']").type(randomEmail); cy.get("input[placeholder='jane@doe.com']").type(randomEmail);
cy.get("input[placeholder='First Name']").type(randomName); cy.get("input[placeholder='Jane']").type(randomName);
cy.get("button").contains("Add").click(); cy.get("button").contains("Add").click();
// Add evaluator // Add evaluator
@@ -39,7 +39,7 @@ describe("Batch Creation", () => {
.click(); .click();
const randomEvaluator = `evaluator${dateNow}@example.com`; const randomEvaluator = `evaluator${dateNow}@example.com`;
cy.get("input[placeholder='Email']").type(randomEvaluator); cy.get("input[placeholder='jane@doe.com']").type(randomEvaluator);
cy.get("button").contains("Add").click(); cy.get("button").contains("Add").click();
cy.get("div").contains(randomEvaluator).should("be.visible").click(); cy.get("div").contains(randomEvaluator).should("be.visible").click();

View File

@@ -206,7 +206,7 @@ const progressColumns = computed(() => {
{ {
label: __('Member'), label: __('Member'),
key: 'member_name', key: 'member_name',
width: '50%', width: '60%',
icon: 'user', icon: 'user',
}, },
{ {

View File

@@ -1,78 +1,129 @@
<template> <template>
<div class="flex min-h-0 flex-col text-base"> <div class="flex min-h-0 flex-col text-base">
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between">
<div> <div>
<div class="text-xl font-semibold mb-1 text-ink-gray-9"> <div class="text-xl font-semibold mb-1 text-ink-gray-9">
{{ __(label) }} {{ __(label) }}
</div> </div>
<!-- <div class="text-xs text-ink-gray-5"> <div class="text-ink-gray-6 leading-5">
{{ __(description) }} {{ __(description) }}
</div> --> </div>
</div> </div>
<div class="flex item-center space-x-2"> <div class="flex item-center space-x-2">
<FormControl <Button variant="solid" @click="() => (showForm = !showForm)">
v-model="search"
:placeholder="__('Search')"
type="text"
:debounce="300"
/>
<Button @click="() => (showForm = !showForm)">
<template #prefix> <template #prefix>
<Plus v-if="!showForm" class="size-4 stroke-1.5" /> <Plus class="size-4 stroke-1.5" />
<X v-else class="size-4 stroke-1.5" />
</template> </template>
{{ showForm ? __('Close') : __('New') }} {{ __('New') }}
</Button> </Button>
</div> </div>
</div> </div>
<!-- Form to add new member --> <div class="mt-8 pb-5">
<div v-if="showForm" class="flex items-center space-x-2 my-4">
<FormControl <FormControl
v-model="email" v-model="search"
:placeholder="__('Email')" :placeholder="__('Search')"
type="email" type="text"
class="w-full" :debounce="300"
@keydown.enter="addEvaluator" class="w-1/4 mb-4"
/> >
<Button @click="addEvaluator()" variant="subtle"> <template #prefix>
{{ __('Add') }} <Search class="size-4 stroke-1.5 text-ink-gray-5" />
</Button> </template>
</div> </FormControl>
<div class="overflow-auto h-[60vh]">
<div class="overflow-y-scroll"> <div class="divide-y">
<div class="divide-y"> <div
<div v-for="evaluator in evaluators.data"
v-for="evaluator in evaluators.data" :key="evaluator.evaluator"
@click="openProfile(evaluator.username)" class="cursor-pointer"
class="cursor-pointer" >
> <div class="flex items-center justify-between group py-3">
<div class="flex items-center justify-between py-3"> <div
<div class="flex items-center space-x-3"> class="flex items-center space-x-3"
<Avatar @click="openProfile(evaluator.username)"
:image="evaluator.user_image" >
:label="evaluator.full_name" <Avatar
size="lg" :image="evaluator.user_image"
/> :label="evaluator.full_name"
<div> size="xl"
<div class="text-base font-semibold text-ink-gray-9"> />
{{ evaluator.full_name }} <div class="space-y-1">
</div> <div class="text-base font-semibold text-ink-gray-9">
<div class="text-xs text-ink-gray-5"> {{ evaluator.full_name }}
{{ evaluator.evaluator }} </div>
<div class="text-xs text-ink-gray-5">
{{ evaluator.evaluator }}
</div>
</div> </div>
</div> </div>
<div class="invisible group-hover:visible">
<Button
variant="ghost"
@click="deleteEvaluator(evaluator.evaluator)"
>
<template #icon>
<Trash2 class="size-4 stroke-1.5 text-ink-red-3" />
</template>
</Button>
</div>
</div> </div>
</div> </div>
</div> </div>
<div
v-if="evaluators.length && hasNextPage"
class="flex justify-center mt-4"
>
<Button @click="evaluators.reload()">
<template #prefix>
<RefreshCw class="h-3 w-3 stroke-1.5" />
</template>
{{ __('Load More') }}
</Button>
</div>
</div> </div>
</div> </div>
</div> </div>
<Dialog
v-model="showForm"
:options="{
size: 'xl',
title: __('Add Evaluator'),
actions: [{
label: __('Add'),
variant: 'solid',
onClick({ close }: any) {
addEvaluator(close)
},
}]
}"
>
<template #body-content>
<div v-if="showForm" class="flex items-center">
<FormControl
v-model="email"
:label="__('Email')"
placeholder="jane@doe.com"
type="email"
class="w-full"
@keydown.enter="addEvaluator"
/>
</div>
</template>
</Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { createResource, Button, FormControl, call, Avatar } from 'frappe-ui' import {
Avatar,
Button,
call,
createListResource,
Dialog,
FormControl,
toast,
} from 'frappe-ui'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { Plus, X } from 'lucide-vue-next' import { Plus, Search, Trash2, RefreshCw } from 'lucide-vue-next'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
const show = defineModel('show') const show = defineModel('show')
@@ -95,33 +146,39 @@ const props = defineProps({
}, },
}) })
const evaluators = createResource({ const evaluators = createListResource({
url: 'frappe.client.get_list', doctype: 'Course Evaluator',
makeParams: () => { fields: ['evaluator', 'username', 'full_name', 'user_image'],
return {
doctype: 'Course Evaluator',
fields: ['evaluator', 'full_name', 'user_image', 'username'],
filters: search.value ? { evaluator: ['like', `%${search.value}%`] } : {},
}
},
auto: true, auto: true,
orderBy: 'creation desc',
}) })
const addEvaluator = () => { const addEvaluator = (close: () => void) => {
call('lms.lms.api.add_an_evaluator', { call('lms.lms.api.add_an_evaluator', {
email: email.value, email: email.value,
}).then((data) => {
showForm.value = false
email.value = ''
evaluators.reload()
}) })
.then(() => {
email.value = ''
evaluators.reload()
toast.success(__('Evaluator added successfully'))
close()
})
.catch((error: any) => {
toast.error(__(error.messages[0] || error.messages))
console.error('Error adding evaluator:', error)
})
} }
watch(search, () => { watch(search, () => {
evaluators.update({
filters: {
full_name: ['like', `%${search.value}%`],
},
})
evaluators.reload() evaluators.reload()
}) })
const openProfile = (username) => { const openProfile = (username: string) => {
show.value = false show.value = false
router.push({ router.push({
name: 'Profile', name: 'Profile',
@@ -130,4 +187,18 @@ const openProfile = (username) => {
}, },
}) })
} }
const deleteEvaluator = (evaluator: string) => {
call('lms.lms.api.delete_evaluator', {
evaluator: evaluator,
})
.then(() => {
toast.success(__('Evaluator deleted successfully'))
evaluators.reload()
})
.catch((error: any) => {
toast.error(__(error.messages[0] || error.messages))
console.error('Error deleting evaluator:', error)
})
}
</script> </script>

View File

@@ -5,53 +5,37 @@
<div class="text-xl font-semibold mb-1 text-ink-gray-9"> <div class="text-xl font-semibold mb-1 text-ink-gray-9">
{{ __(label) }} {{ __(label) }}
</div> </div>
<!-- <div class="text-xs text-ink-gray-5"> <div class="text-ink-gray-6 leading-5">
{{ __(description) }} {{ __(description) }}
</div> --> </div>
</div> </div>
<div class="flex item-center space-x-2"> <div class="flex item-center space-x-2">
<FormControl <Button variant="solid" @click="() => (showForm = !showForm)">
v-model="search"
:placeholder="__('Search')"
type="text"
:debounce="300"
/>
<Button @click="() => (showForm = !showForm)">
<template #prefix> <template #prefix>
<Plus v-if="!showForm" class="size-4 stroke-1.5" /> <Plus class="size-4 stroke-1.5" />
<X v-else class="size-4 stroke-1.5" />
</template> </template>
{{ showForm ? __('Close') : __('New') }} {{ __('New') }}
</Button> </Button>
</div> </div>
</div> </div>
<!-- Form to add new member --> <div class="mt-8 pb-10">
<div v-if="showForm" class="flex items-center space-x-2 my-4">
<FormControl <FormControl
v-model="member.email" v-model="search"
:placeholder="__('Email')" :placeholder="__('Search')"
type="email"
class="w-full"
/>
<FormControl
v-model="member.first_name"
:placeholder="__('First Name')"
type="text" type="text"
class="w-full" :debounce="300"
/> class="w-1/4 mb-4"
<Button @click="addMember()" variant="subtle"> >
{{ __('Add') }} <template #prefix>
</Button> <Search class="size-4 stroke-1.5 text-ink-gray-5" />
</div> </template>
</FormControl>
<div class="mt-2 pb-10 overflow-auto"> <div class="overflow-y-scroll h-[60vh]">
<!-- Member list -->
<div class="overflow-y-scroll">
<ul class="divide-y"> <ul class="divide-y">
<li <li
v-for="member in memberList" v-for="member in memberList"
class="grid grid-cols-3 gap-10 py-2 cursor-pointer" class="flex items-center justify-between py-2 cursor-pointer"
> >
<div <div
@click="openProfile(member.username)" @click="openProfile(member.username)"
@@ -60,27 +44,13 @@
<Avatar <Avatar
:image="member.user_image" :image="member.user_image"
:label="member.full_name" :label="member.full_name"
size="lg" size="xl"
/> />
<div class="space-y-1"> <div class="space-y-1">
<div class="flex"> <div class="flex">
<div class="text-ink-gray-9"> <div class="text-ink-gray-9">
{{ member.full_name }} {{ member.full_name }}
</div> </div>
<div
class="px-1"
v-if="member.role && getRole(member.role) !== 'Student'"
>
<Badge
:variant="'subtle'"
:ref_for="true"
theme="blue"
size="sm"
label="Badge"
>
{{ getRole(member.role) }}
</Badge>
</div>
</div> </div>
<div class="text-sm text-ink-gray-7"> <div class="text-sm text-ink-gray-7">
{{ member.name }} {{ member.name }}
@@ -88,43 +58,92 @@
</div> </div>
</div> </div>
<div <div
class="flex items-center justify-center text-ink-gray-7 text-sm" class="flex items-center space-x-1 bg-surface-gray-2 px-2 py-1.5 rounded-md"
v-if="member.role && member.role !== 'LMS Student'"
> >
<div v-if="member.last_active"> <Shield class="size-4 stroke-1.5" />
{{ dayjs(member.last_active).format('DD MMM, YYYY HH:mm a') }} <span class="text-sm">
</div> {{ getRole(member.role) }}
<div v-else>-</div> </span>
</div> </div>
</li> </li>
</ul> </ul>
</div> <div
<div v-if="memberList.length && hasNextPage"
v-if="memberList.length && hasNextPage" class="flex justify-center mt-4"
class="flex justify-center mt-4" >
> <Button @click="members.reload()">
<Button @click="members.reload()"> <template #prefix>
<template #prefix> <RefreshCw class="h-3 w-3 stroke-1.5" />
<RefreshCw class="h-3 w-3 stroke-1.5" /> </template>
</template> {{ __('Load More') }}
{{ __('Load More') }} </Button>
</Button> </div>
</div> </div>
</div> </div>
</div> </div>
<Dialog
v-model="showForm"
:options="{
title: __('Add a new member'),
size: 'lg',
actions: [{
label: __('Add'),
variant: 'solid',
onClick({ close }: any) {
addMember(close)
}
}]
}"
>
<template #body-content>
<div class="flex items-center space-x-2">
<FormControl
v-model="member.email"
:label="__('Email')"
placeholder="jane@doe.com"
type="email"
class="w-full"
/>
<FormControl
v-model="member.first_name"
:label="__('First Name')"
placeholder="Jane"
type="text"
class="w-full"
/>
</div>
</template>
</Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { createResource, Avatar, Button, FormControl, Badge } from 'frappe-ui' import {
Avatar,
Badge,
Button,
createResource,
Dialog,
FormControl,
} from 'frappe-ui'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ref, watch, reactive, inject } from 'vue' import { ref, watch, reactive, inject } from 'vue'
import { RefreshCw, Plus, X } from 'lucide-vue-next' import { RefreshCw, Plus, Search, Shield } from 'lucide-vue-next'
import { useOnboarding } from 'frappe-ui/frappe' import { useOnboarding } from 'frappe-ui/frappe'
import type { User } from '@/components/Settings/types' import type { User } from '@/components/Settings/types'
type Member = {
username: string
full_name: string
name: string
role?: string
user_image?: string
}
const router = useRouter() const router = useRouter()
const show = defineModel('show') const show = defineModel('show')
const search = ref('') const search = ref('')
const start = ref(0) const start = ref(0)
const memberList = ref([]) const memberList = ref<Member[]>([])
const hasNextPage = ref(false) const hasNextPage = ref(false)
const showForm = ref(false) const showForm = ref(false)
const dayjs = inject('$dayjs') const dayjs = inject('$dayjs')
@@ -158,7 +177,7 @@ const members = createResource({
start: start.value, start: start.value,
} }
}, },
onSuccess(data) { onSuccess(data: Member[]) {
memberList.value = memberList.value.concat(data) memberList.value = memberList.value.concat(data)
start.value = start.value + 20 start.value = start.value + 20
hasNextPage.value = data.length === 20 hasNextPage.value = data.length === 20
@@ -166,7 +185,7 @@ const members = createResource({
auto: true, auto: true,
}) })
const openProfile = (username) => { const openProfile = (username: string) => {
show.value = false show.value = false
router.push({ router.push({
name: 'Profile', name: 'Profile',
@@ -178,7 +197,7 @@ const openProfile = (username) => {
const newMember = createResource({ const newMember = createResource({
url: 'frappe.client.insert', url: 'frappe.client.insert',
makeParams(values) { makeParams() {
return { return {
doc: { doc: {
doctype: 'User', doctype: 'User',
@@ -188,13 +207,12 @@ const newMember = createResource({
} }
}, },
auto: false, auto: false,
onSuccess(data) { onSuccess(data: Member) {
show.value = false show.value = false
if (user?.data?.is_system_manager) updateOnboardingStep('invite_students') if (user?.data?.is_system_manager) updateOnboardingStep('invite_students')
router.push({ router.push({
name: 'Profile', name: 'ProfileRoles',
params: { params: {
username: data.username, username: data.username,
}, },
@@ -202,8 +220,9 @@ const newMember = createResource({
}, },
}) })
const addMember = () => { const addMember = (close: () => void) => {
newMember.reload() newMember.reload()
close()
} }
watch(search, () => { watch(search, () => {
@@ -212,8 +231,8 @@ watch(search, () => {
members.reload() members.reload()
}) })
const getRole = (role) => { const getRole = (role: string) => {
const map = { const map: Record<string, string> = {
'LMS Student': 'Student', 'LMS Student': 'Student',
'Course Creator': 'Instructor', 'Course Creator': 'Instructor',
Moderator: 'Moderator', Moderator: 'Moderator',

View File

@@ -242,13 +242,16 @@ const tabsStructure = computed(() => {
items: [ items: [
{ {
label: 'Members', label: 'Members',
description: 'Manage the members of your learning system', description:
'Add new members or manage roles and permissions of existing members',
icon: 'UserRoundPlus', icon: 'UserRoundPlus',
}, },
{ {
label: 'Evaluators', label: 'Evaluators',
description: 'Manage the evaluators of your learning system', description: '',
icon: 'UserCheck', icon: 'UserCheck',
description:
'Add new evaluators or check the slots existing evaluators',
}, },
{ {
label: 'Categories', label: 'Categories',

View File

@@ -80,7 +80,7 @@
v-model="activeTab" v-model="activeTab"
/> />
</div> </div>
<router-view :profile="profile" /> <router-view :profile="profile" :key="profile.data?.name" />
</div> </div>
</div> </div>
<EditProfile <EditProfile

View File

@@ -45,7 +45,7 @@
</template> </template>
<script setup> <script setup>
import { FormControl, createResource, toast } from 'frappe-ui' import { FormControl, createResource, toast } from 'frappe-ui'
import { ref } from 'vue' import { ref, watch } from 'vue'
import { convertToTitleCase } from '@/utils' import { convertToTitleCase } from '@/utils'
import { CircleAlert } from 'lucide-vue-next' import { CircleAlert } from 'lucide-vue-next'
@@ -66,10 +66,9 @@ const roles = createResource({
url: 'lms.lms.utils.get_roles', url: 'lms.lms.utils.get_roles',
makeParams(values) { makeParams(values) {
return { return {
name: props.profile.data?.name, name: values.member,
} }
}, },
auto: true,
onSuccess(data) { onSuccess(data) {
let roles = [ let roles = [
'moderator', 'moderator',
@@ -83,6 +82,16 @@ const roles = createResource({
}, },
}) })
watch(
() => props.profile,
(newValue) => {
roles.reload({
member: newValue.data?.name,
})
},
{ immediate: true }
)
const updateRole = createResource({ const updateRole = createResource({
url: 'lms.lms.api.save_role', url: 'lms.lms.api.save_role',
makeParams(values) { makeParams(values) {
@@ -97,7 +106,10 @@ const updateRole = createResource({
const changeRole = (role) => { const changeRole = (role) => {
updateRole.submit( updateRole.submit(
{ {
role: convertToTitleCase(role.split('_').join(' ')), role:
role == 'lms_student'
? 'LMS Student'
: convertToTitleCase(role.split('_').join(' ')),
value: eval(role).value, value: eval(role).value,
}, },
{ {

View File

@@ -696,15 +696,6 @@ def get_categories(doctype, filters):
@frappe.whitelist() @frappe.whitelist()
def get_members(start=0, search=""): def get_members(start=0, search=""):
"""Get members for the given search term and start index.
Args: start (int): Start index for the query.
<<<<<<< HEAD
search (str): Search term to filter the results.
=======
search (str): Search term to filter the results.
>>>>>>> 4869bba7bbb2fb38477d6fc29fb3b5838e075577
Returns: List of members.
"""
filters = {"enabled": 1, "name": ["not in", ["Administrator", "Guest"]]} filters = {"enabled": 1, "name": ["not in", ["Administrator", "Guest"]]}
or_filters = {} or_filters = {}
@@ -723,7 +714,14 @@ def get_members(start=0, search=""):
) )
for member in members: for member in members:
roles = frappe.get_roles(member.name) roles = frappe.get_all(
"Has Role",
{
"parent": member.name,
"parenttype": "User",
},
pluck="role",
)
if "Moderator" in roles: if "Moderator" in roles:
member.role = "Moderator" member.role = "Moderator"
elif "Course Creator" in roles: elif "Course Creator" in roles:
@@ -1394,6 +1392,7 @@ def save_role(user, role, value):
@frappe.whitelist() @frappe.whitelist()
def add_an_evaluator(email): def add_an_evaluator(email):
frappe.only_for("Moderator")
if not frappe.db.exists("User", email): if not frappe.db.exists("User", email):
user = frappe.new_doc("User") user = frappe.new_doc("User")
user.update( user.update(
@@ -1413,6 +1412,16 @@ def add_an_evaluator(email):
return evaluator return evaluator
@frappe.whitelist()
def delete_evaluator(evaluator):
frappe.only_for("Moderator")
if not frappe.db.exists("Course Evaluator", evaluator):
frappe.throw(_("Evaluator does not exist."))
frappe.db.delete("Has Role", {"parent": evaluator, "role": "Batch Evaluator"})
frappe.db.delete("Course Evaluator", evaluator)
@frappe.whitelist() @frappe.whitelist()
def capture_user_persona(responses): def capture_user_persona(responses):
frappe.only_for("System Manager") frappe.only_for("System Manager")
@@ -1574,7 +1583,7 @@ def track_video_watch_duration(lesson, videos):
existing_record = frappe.db.get_value( existing_record = frappe.db.get_value(
"LMS Video Watch Duration", filters, ["name", "watch_time"], as_dict=True "LMS Video Watch Duration", filters, ["name", "watch_time"], as_dict=True
) )
if existing_record and existing_record.watch_time < video.get("watch_time"): if existing_record and flt(existing_record.watch_time) < flt(video.get("watch_time")):
frappe.db.set_value( frappe.db.set_value(
"LMS Video Watch Duration", "LMS Video Watch Duration",
filters, filters,

View File

@@ -58,8 +58,7 @@
"fetch_from": "evaluator.full_name", "fetch_from": "evaluator.full_name",
"fieldname": "full_name", "fieldname": "full_name",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Full Name", "label": "Full Name"
"read_only": 1
}, },
{ {
"fieldname": "column_break_casg", "fieldname": "column_break_casg",
@@ -73,21 +72,19 @@
"fetch_from": "evaluator.user_image", "fetch_from": "evaluator.user_image",
"fieldname": "user_image", "fieldname": "user_image",
"fieldtype": "Attach Image", "fieldtype": "Attach Image",
"label": "User Image", "label": "User Image"
"read_only": 1
}, },
{ {
"fetch_from": "evaluator.username", "fetch_from": "evaluator.username",
"fieldname": "username", "fieldname": "username",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Username", "label": "Username"
"read_only": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2025-06-05 11:04:32.475711", "modified": "2025-07-04 12:04:11.007945",
"modified_by": "sayali@frappe.io", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Course Evaluator", "name": "Course Evaluator",
"naming_rule": "By fieldname", "naming_rule": "By fieldname",

View File

@@ -1,6 +1,7 @@
{ {
"attach_print": 0, "attach_print": 0,
"channel": "Email", "channel": "Email",
"condition": "doc.status == \"Upcoming\"",
"creation": "2022-06-03 11:51:02.681803", "creation": "2022-06-03 11:51:02.681803",
"date_changed": "date", "date_changed": "date",
"days_in_advance": 1, "days_in_advance": 1,
@@ -13,7 +14,8 @@
"is_standard": 1, "is_standard": 1,
"message": "<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<br>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(doc.course_title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), doc.timezone) }}</p>\n<br>\n<p> {{ _(\"{0} is your evaluator\").format(doc.evaluator_name) }} </p>\n<br>\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n", "message": "<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<br>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(doc.course_title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), doc.timezone) }}</p>\n<br>\n<p> {{ _(\"{0} is your evaluator\").format(doc.evaluator_name) }} </p>\n<br>\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
"message_type": "HTML", "message_type": "HTML",
"modified": "2024-09-05 16:33:42.212842", "minutes_offset": 0,
"modified": "2025-07-04 10:47:58.448814",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Certificate Request Reminder", "name": "Certificate Request Reminder",
@@ -22,6 +24,12 @@
{ {
"receiver_by_document_field": "member" "receiver_by_document_field": "member"
}, },
{
"receiver_by_document_field": "member"
},
{
"receiver_by_document_field": "evaluator"
},
{ {
"receiver_by_document_field": "evaluator" "receiver_by_document_field": "evaluator"
} }

View File

@@ -537,11 +537,10 @@ def has_course_evaluator_role(member=None):
def has_student_role(member=None): def has_student_role(member=None):
roles = frappe.get_roles(member or frappe.session.user) return frappe.db.get_value(
return ( "Has Role",
"Moderator" not in roles {"parent": member or frappe.session.user, "role": "LMS Student"},
and "Course Creator" not in roles "name",
and "Batch Evaluator" not in roles
) )

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n" "Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n" "Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-06-27 16:04+0000\n" "POT-Creation-Date: 2025-06-27 16:04+0000\n"
"PO-Revision-Date: 2025-06-30 19:09\n" "PO-Revision-Date: 2025-07-03 19:53\n"
"Last-Translator: jannat@frappe.io\n" "Last-Translator: jannat@frappe.io\n"
"Language-Team: Serbian (Cyrillic)\n" "Language-Team: Serbian (Cyrillic)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -165,7 +165,7 @@ msgstr "Додај термин"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:35 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:35
msgid "Add Test Case" msgid "Add Test Case"
msgstr "" msgstr "Додај тест пример"
#: lms/templates/onboarding_header.html:26 #: lms/templates/onboarding_header.html:26
msgid "Add a Chapter" msgid "Add a Chapter"
@@ -202,7 +202,7 @@ msgstr "Додај ново питање"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:5 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:5
msgid "Add a programming exercise to your lesson" msgid "Add a programming exercise to your lesson"
msgstr "" msgstr "Додај вежбу програмирања у своју лекцију"
#: frontend/src/components/AssessmentPlugin.vue:7 #: frontend/src/components/AssessmentPlugin.vue:7
msgid "Add a quiz to your lesson" msgid "Add a quiz to your lesson"
@@ -532,7 +532,7 @@ msgstr "Бар једна опција мора бити тачна за ово
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.py:15 #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.py:15
msgid "At least one test case is required for the programming exercise." msgid "At least one test case is required for the programming exercise."
msgstr "" msgstr "Најмање један тест пример је неопходан за вежбу програмирања."
#: frontend/src/components/Modals/LiveClassAttendance.vue:5 #: frontend/src/components/Modals/LiveClassAttendance.vue:5
msgid "Attendance for Class - {0}" msgid "Attendance for Class - {0}"
@@ -967,7 +967,7 @@ msgstr "Означи"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:16 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:16
msgid "Check All Submissions" msgid "Check All Submissions"
msgstr "" msgstr "Провери све поднеске"
#: lms/templates/emails/mention_template.html:10 #: lms/templates/emails/mention_template.html:10
msgid "Check Discussion" msgid "Check Discussion"
@@ -975,7 +975,7 @@ msgstr "Провери дискусију"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:97 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:97
msgid "Check Submission" msgid "Check Submission"
msgstr "" msgstr "Провери поднесак"
#: frontend/src/components/Modals/AssignmentForm.vue:55 #: frontend/src/components/Modals/AssignmentForm.vue:55
msgid "Check Submissions" msgid "Check Submissions"
@@ -1213,7 +1213,7 @@ msgstr "Веб-сајт компаније"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:68 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:68
msgid "Compiler Message" msgid "Compiler Message"
msgstr "" msgstr "Порука компајлера"
#. Option for the 'Status' (Select) field in DocType 'LMS Course Progress' #. Option for the 'Status' (Select) field in DocType 'LMS Course Progress'
#: frontend/src/components/Modals/BatchStudentProgress.vue:24 #: frontend/src/components/Modals/BatchStudentProgress.vue:24
@@ -1585,7 +1585,7 @@ msgstr "Креирај нови"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:7 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:7
msgid "Create Programming Exercise" msgid "Create Programming Exercise"
msgstr "" msgstr "Креирај вежбу програмирања"
#: lms/templates/onboarding_header.html:19 #: lms/templates/onboarding_header.html:19
msgid "Create a Course" msgid "Create a Course"
@@ -1926,7 +1926,7 @@ msgstr "Уреди профил"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:8 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:8
msgid "Edit Programming Exercise" msgid "Edit Programming Exercise"
msgstr "" msgstr "Уреди вежбу програмирања"
#: frontend/src/components/Modals/ZoomAccountModal.vue:6 #: frontend/src/components/Modals/ZoomAccountModal.vue:6
msgid "Edit Zoom Account" msgid "Edit Zoom Account"
@@ -2265,7 +2265,7 @@ msgstr "Прошири"
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Expected Output" msgid "Expected Output"
msgstr "" msgstr "Очекивани излаз"
#. Label of the expiration_date (Data) field in DocType 'Certification' #. Label of the expiration_date (Data) field in DocType 'Certification'
#: lms/lms/doctype/certification/certification.json #: lms/lms/doctype/certification/certification.json
@@ -2322,7 +2322,7 @@ msgstr "Неуспешно преузимање података о присус
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:353 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:353
msgid "Failed to submit. Please try again. {0}" msgid "Failed to submit. Please try again. {0}"
msgstr "" msgstr "Неуспешно подношење. Покушајте поново. {0}"
#: frontend/src/utils/index.js:636 #: frontend/src/utils/index.js:636
msgid "Failed to update meta tags {0}" msgid "Failed to update meta tags {0}"
@@ -2363,15 +2363,15 @@ msgstr "Врста фајла"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:23 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:23
msgid "Filter by Exercise" msgid "Filter by Exercise"
msgstr "" msgstr "Филтрирај по вежби"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:28 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:28
msgid "Filter by Member" msgid "Filter by Member"
msgstr "" msgstr "Филтрирај по члану"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:39 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:39
msgid "Filter by Status" msgid "Filter by Status"
msgstr "" msgstr "Филтрирај по статусу"
#: frontend/src/components/Modals/EditProfile.vue:59 #: frontend/src/components/Modals/EditProfile.vue:59
#: frontend/src/components/Settings/Members.vue:39 #: frontend/src/components/Settings/Members.vue:39
@@ -2758,7 +2758,7 @@ msgstr "Индустрија"
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Input" msgid "Input"
msgstr "" msgstr "Улаз"
#. Label of the institution_name (Data) field in DocType 'Education Detail' #. Label of the institution_name (Data) field in DocType 'Education Detail'
#: lms/lms/doctype/education_detail/education_detail.json #: lms/lms/doctype/education_detail/education_detail.json
@@ -3149,12 +3149,12 @@ msgstr "LMS члан програма"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
msgid "LMS Programming Exercise" msgid "LMS Programming Exercise"
msgstr "" msgstr "LMS вежба програмирања"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json #: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
msgid "LMS Programming Exercise Submission" msgid "LMS Programming Exercise Submission"
msgstr "" msgstr "LMS поднесак вежбе програмирања"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_question/lms_question.json #: lms/lms/doctype/lms_question/lms_question.json
@@ -3228,12 +3228,12 @@ msgstr "LMS студент"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
msgid "LMS Test Case" msgid "LMS Test Case"
msgstr "" msgstr "LMS тест пример"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "LMS Test Case Submission" msgid "LMS Test Case Submission"
msgstr "" msgstr "LMS поднесак тест примера"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_timetable_legend/lms_timetable_legend.json #: lms/lms/doctype/lms_timetable_legend/lms_timetable_legend.json
@@ -3793,7 +3793,7 @@ msgstr "Модератор"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:280 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:280
msgid "Modified" msgid "Modified"
msgstr "" msgstr "Измењено"
#: lms/lms/doctype/lms_badge/lms_badge.js:40 #: lms/lms/doctype/lms_badge/lms_badge.js:40
msgid "Modified By" msgid "Modified By"
@@ -3941,7 +3941,7 @@ msgstr "Нема снимка"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:13 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:13
msgid "No Submissions" msgid "No Submissions"
msgstr "" msgstr "Нема поднесака"
#: lms/templates/upcoming_evals.html:43 #: lms/templates/upcoming_evals.html:43
msgid "No Upcoming Evaluations" msgid "No Upcoming Evaluations"
@@ -4262,7 +4262,7 @@ msgstr "Положено"
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json #: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Passed" msgid "Passed"
msgstr "" msgstr "Задовољава"
#. Label of the passing_percentage (Int) field in DocType 'LMS Quiz' #. Label of the passing_percentage (Int) field in DocType 'LMS Quiz'
#. Label of the passing_percentage (Int) field in DocType 'LMS Quiz Submission' #. Label of the passing_percentage (Int) field in DocType 'LMS Quiz Submission'
@@ -4483,7 +4483,7 @@ msgstr "Молимо Вас да се добро припремите и сти
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:133 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:133
msgid "Please run the code to execute the test cases." msgid "Please run the code to execute the test cases."
msgstr "" msgstr "Молимо Вас да покренете код да бисте извршили тест примере."
#: frontend/src/components/UpcomingEvaluations.vue:98 #: frontend/src/components/UpcomingEvaluations.vue:98
msgid "Please schedule an evaluation to get certified." msgid "Please schedule an evaluation to get certified."
@@ -4658,7 +4658,7 @@ msgstr "Приватне информације укључују Вашу оце
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:25 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:25
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
msgid "Problem Statement" msgid "Problem Statement"
msgstr "" msgstr "Опис проблема"
#: frontend/src/pages/Billing.vue:129 #: frontend/src/pages/Billing.vue:129
msgid "Proceed to Payment" msgid "Proceed to Payment"
@@ -4695,34 +4695,34 @@ msgstr "Чланови програма"
#: frontend/src/components/Assessments.vue:249 #: frontend/src/components/Assessments.vue:249
msgid "Programming Exercise" msgid "Programming Exercise"
msgstr "" msgstr "Вежба програмирања"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:415 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:415
msgid "Programming Exercise Submission" msgid "Programming Exercise Submission"
msgstr "" msgstr "Поднесак вежбе програмирања"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:406 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:406
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:292 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:292
msgid "Programming Exercise Submissions" msgid "Programming Exercise Submissions"
msgstr "" msgstr "Поднесци вежбе програмирања"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:211 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:211
msgid "Programming Exercise created successfully" msgid "Programming Exercise created successfully"
msgstr "" msgstr "Вежба програмирања је успешно креирана"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:247 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:247
msgid "Programming Exercise deleted successfully" msgid "Programming Exercise deleted successfully"
msgstr "" msgstr "Вежба програмирања је успешно обрисана"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:230 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:230
msgid "Programming Exercise updated successfully" msgid "Programming Exercise updated successfully"
msgstr "" msgstr "Вежба програмирања је успешно ажурирана"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:302 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:302
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:157 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:157
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:165 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:165
msgid "Programming Exercises" msgid "Programming Exercises"
msgstr "" msgstr "Вежбе програмирања"
#: frontend/src/pages/Programs.vue:206 frontend/src/pages/Programs.vue:212 #: frontend/src/pages/Programs.vue:206 frontend/src/pages/Programs.vue:212
#: lms/www/lms.py:295 #: lms/www/lms.py:295
@@ -5224,7 +5224,7 @@ msgstr "Преостала места"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:23 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:23
msgid "Select a Programming Exercise" msgid "Select a Programming Exercise"
msgstr "" msgstr "Изаберите вежбу програмирања"
#: frontend/src/components/Modals/Question.vue:98 #: frontend/src/components/Modals/Question.vue:98
msgid "Select a question" msgid "Select a question"
@@ -5637,11 +5637,11 @@ msgstr "Поднето од стране"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:348 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:348
msgid "Submission saved!" msgid "Submission saved!"
msgstr "" msgstr "Поднесак је сачуван!"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:248 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:248
msgid "Submissions deleted successfully" msgid "Submissions deleted successfully"
msgstr "" msgstr "Поднесци су успешно обрисани"
#: frontend/src/components/Modals/AssessmentModal.vue:9 #: frontend/src/components/Modals/AssessmentModal.vue:9
#: frontend/src/components/Modals/BatchCourseModal.vue:9 #: frontend/src/components/Modals/BatchCourseModal.vue:9
@@ -5786,7 +5786,7 @@ msgstr "Услови коришћења"
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json #: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
msgid "Test Cases" msgid "Test Cases"
msgstr "" msgstr "Тест примери"
#. Label of the test_results (Small Text) field in DocType 'Exercise Latest #. Label of the test_results (Small Text) field in DocType 'Exercise Latest
#. Submission' #. Submission'
@@ -5799,11 +5799,11 @@ msgstr "Резултати теста"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:82 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:82
msgid "Test this Exercise" msgid "Test this Exercise"
msgstr "" msgstr "Тестирај ову вежбу"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:90 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:90
msgid "Test {0}" msgid "Test {0}"
msgstr "" msgstr "Тест {0}"
#. Label of the tests (Code) field in DocType 'LMS Exercise' #. Label of the tests (Code) field in DocType 'LMS Exercise'
#: lms/lms/doctype/lms_exercise/lms_exercise.json #: lms/lms/doctype/lms_exercise/lms_exercise.json
@@ -5974,7 +5974,7 @@ msgstr "Временска преференција"
#: frontend/src/components/VideoBlock.vue:140 #: frontend/src/components/VideoBlock.vue:140
msgid "Time for a Quiz" msgid "Time for a Quiz"
msgstr "" msgstr "Време за квиз"
#: frontend/src/components/Modals/QuizInVideo.vue:13 #: frontend/src/components/Modals/QuizInVideo.vue:13
msgid "Time in Video" msgid "Time in Video"
@@ -6642,7 +6642,7 @@ msgstr "Ваш налог је успешно креиран!"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:117 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:117
msgid "Your Output" msgid "Your Output"
msgstr "" msgstr "Твој излаз"
#: lms/lms/doctype/lms_batch/lms_batch.py:362 #: lms/lms/doctype/lms_batch/lms_batch.py:362
msgid "Your batch {0} is starting tomorrow" msgid "Your batch {0} is starting tomorrow"
@@ -6824,7 +6824,7 @@ msgstr "{0} задатака"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:39 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:39
msgid "{0} Exercises" msgid "{0} Exercises"
msgstr "" msgstr "{0} вежби"
#: frontend/src/pages/Jobs.vue:32 #: frontend/src/pages/Jobs.vue:32
msgid "{0} Open Jobs" msgid "{0} Open Jobs"
@@ -6840,7 +6840,7 @@ msgstr "{0} подешавања нису пронађена"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:12 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:12
msgid "{0} Submissions" msgid "{0} Submissions"
msgstr "" msgstr "{0} поднесака"
#: lms/templates/emails/job_application.html:2 #: lms/templates/emails/job_application.html:2
msgid "{0} has applied for the job position {1}" msgid "{0} has applied for the job position {1}"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n" "Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n" "Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-06-27 16:04+0000\n" "POT-Creation-Date: 2025-06-27 16:04+0000\n"
"PO-Revision-Date: 2025-06-30 19:09\n" "PO-Revision-Date: 2025-07-03 19:53\n"
"Last-Translator: jannat@frappe.io\n" "Last-Translator: jannat@frappe.io\n"
"Language-Team: Serbian (Latin)\n" "Language-Team: Serbian (Latin)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -165,7 +165,7 @@ msgstr "Dodaj termin"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:35 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:35
msgid "Add Test Case" msgid "Add Test Case"
msgstr "" msgstr "Dodaj test primer"
#: lms/templates/onboarding_header.html:26 #: lms/templates/onboarding_header.html:26
msgid "Add a Chapter" msgid "Add a Chapter"
@@ -202,7 +202,7 @@ msgstr "Dodaj novo pitanje"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:5 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:5
msgid "Add a programming exercise to your lesson" msgid "Add a programming exercise to your lesson"
msgstr "" msgstr "Dodaj vežbu programiranja u svoju lekciju"
#: frontend/src/components/AssessmentPlugin.vue:7 #: frontend/src/components/AssessmentPlugin.vue:7
msgid "Add a quiz to your lesson" msgid "Add a quiz to your lesson"
@@ -532,7 +532,7 @@ msgstr "Bar jedna opcija mora biti tačna za ovo pitanje."
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.py:15 #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.py:15
msgid "At least one test case is required for the programming exercise." msgid "At least one test case is required for the programming exercise."
msgstr "" msgstr "Najmanje jedan test primer je neophodan za vežbu programiranja."
#: frontend/src/components/Modals/LiveClassAttendance.vue:5 #: frontend/src/components/Modals/LiveClassAttendance.vue:5
msgid "Attendance for Class - {0}" msgid "Attendance for Class - {0}"
@@ -967,7 +967,7 @@ msgstr "Označi"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:16 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:16
msgid "Check All Submissions" msgid "Check All Submissions"
msgstr "" msgstr "Proveri sve podneske"
#: lms/templates/emails/mention_template.html:10 #: lms/templates/emails/mention_template.html:10
msgid "Check Discussion" msgid "Check Discussion"
@@ -975,7 +975,7 @@ msgstr "Proveri diskusiju"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:97 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:97
msgid "Check Submission" msgid "Check Submission"
msgstr "" msgstr "Proveri podnesak"
#: frontend/src/components/Modals/AssignmentForm.vue:55 #: frontend/src/components/Modals/AssignmentForm.vue:55
msgid "Check Submissions" msgid "Check Submissions"
@@ -1213,7 +1213,7 @@ msgstr "Veb-sajt kompanije"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:68 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:68
msgid "Compiler Message" msgid "Compiler Message"
msgstr "" msgstr "Poruka kompajlera"
#. Option for the 'Status' (Select) field in DocType 'LMS Course Progress' #. Option for the 'Status' (Select) field in DocType 'LMS Course Progress'
#: frontend/src/components/Modals/BatchStudentProgress.vue:24 #: frontend/src/components/Modals/BatchStudentProgress.vue:24
@@ -1585,7 +1585,7 @@ msgstr "Kreiraj novi"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:7 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:7
msgid "Create Programming Exercise" msgid "Create Programming Exercise"
msgstr "" msgstr "Kreiraj vežbu programiranja"
#: lms/templates/onboarding_header.html:19 #: lms/templates/onboarding_header.html:19
msgid "Create a Course" msgid "Create a Course"
@@ -1926,7 +1926,7 @@ msgstr "Uredi profil"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:8 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:8
msgid "Edit Programming Exercise" msgid "Edit Programming Exercise"
msgstr "" msgstr "Uredi vežbu programiranja"
#: frontend/src/components/Modals/ZoomAccountModal.vue:6 #: frontend/src/components/Modals/ZoomAccountModal.vue:6
msgid "Edit Zoom Account" msgid "Edit Zoom Account"
@@ -2265,7 +2265,7 @@ msgstr "Proširi"
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Expected Output" msgid "Expected Output"
msgstr "" msgstr "Očekivani izlaz"
#. Label of the expiration_date (Data) field in DocType 'Certification' #. Label of the expiration_date (Data) field in DocType 'Certification'
#: lms/lms/doctype/certification/certification.json #: lms/lms/doctype/certification/certification.json
@@ -2322,7 +2322,7 @@ msgstr "Neuspešno preuzimanje podataka o prisustvu za Zoom za predavanje {0}: {
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:353 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:353
msgid "Failed to submit. Please try again. {0}" msgid "Failed to submit. Please try again. {0}"
msgstr "" msgstr "Neuspešno podnošenje. Pokušajte ponovo. {0}"
#: frontend/src/utils/index.js:636 #: frontend/src/utils/index.js:636
msgid "Failed to update meta tags {0}" msgid "Failed to update meta tags {0}"
@@ -2363,15 +2363,15 @@ msgstr "Vrsta fajla"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:23 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:23
msgid "Filter by Exercise" msgid "Filter by Exercise"
msgstr "" msgstr "Filtriraj po vežbi"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:28 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:28
msgid "Filter by Member" msgid "Filter by Member"
msgstr "" msgstr "Filtriraj po članu"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:39 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:39
msgid "Filter by Status" msgid "Filter by Status"
msgstr "" msgstr "Filtriraj po statusu"
#: frontend/src/components/Modals/EditProfile.vue:59 #: frontend/src/components/Modals/EditProfile.vue:59
#: frontend/src/components/Settings/Members.vue:39 #: frontend/src/components/Settings/Members.vue:39
@@ -2758,7 +2758,7 @@ msgstr "Industrija"
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "Input" msgid "Input"
msgstr "" msgstr "Ulaz"
#. Label of the institution_name (Data) field in DocType 'Education Detail' #. Label of the institution_name (Data) field in DocType 'Education Detail'
#: lms/lms/doctype/education_detail/education_detail.json #: lms/lms/doctype/education_detail/education_detail.json
@@ -3149,12 +3149,12 @@ msgstr "LMS član programa"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
msgid "LMS Programming Exercise" msgid "LMS Programming Exercise"
msgstr "" msgstr "LMS vežba programiranja"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json #: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
msgid "LMS Programming Exercise Submission" msgid "LMS Programming Exercise Submission"
msgstr "" msgstr "LMS podnesak vežbe programiranja"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_question/lms_question.json #: lms/lms/doctype/lms_question/lms_question.json
@@ -3228,12 +3228,12 @@ msgstr "LMS student"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_test_case/lms_test_case.json #: lms/lms/doctype/lms_test_case/lms_test_case.json
msgid "LMS Test Case" msgid "LMS Test Case"
msgstr "" msgstr "LMS test primer"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json #: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
msgid "LMS Test Case Submission" msgid "LMS Test Case Submission"
msgstr "" msgstr "LMS podnesak test primera"
#. Name of a DocType #. Name of a DocType
#: lms/lms/doctype/lms_timetable_legend/lms_timetable_legend.json #: lms/lms/doctype/lms_timetable_legend/lms_timetable_legend.json
@@ -3793,7 +3793,7 @@ msgstr "Moderator"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:280 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:280
msgid "Modified" msgid "Modified"
msgstr "" msgstr "Izmenjeno"
#: lms/lms/doctype/lms_badge/lms_badge.js:40 #: lms/lms/doctype/lms_badge/lms_badge.js:40
msgid "Modified By" msgid "Modified By"
@@ -3941,7 +3941,7 @@ msgstr "Nema snimka"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:13 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:13
msgid "No Submissions" msgid "No Submissions"
msgstr "" msgstr "Nema podnesaka"
#: lms/templates/upcoming_evals.html:43 #: lms/templates/upcoming_evals.html:43
msgid "No Upcoming Evaluations" msgid "No Upcoming Evaluations"
@@ -4483,7 +4483,7 @@ msgstr "Molimo Vas da se dobro pripremite i stignete na vreme za ocenjivanje."
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:133 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:133
msgid "Please run the code to execute the test cases." msgid "Please run the code to execute the test cases."
msgstr "" msgstr "Molimo Vas da pokrenete kod da biste izvršili test primere."
#: frontend/src/components/UpcomingEvaluations.vue:98 #: frontend/src/components/UpcomingEvaluations.vue:98
msgid "Please schedule an evaluation to get certified." msgid "Please schedule an evaluation to get certified."
@@ -4658,7 +4658,7 @@ msgstr "Privatne informacije uključuju Vašu ocenu i želje vezane za radno okr
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:25 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:25
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
msgid "Problem Statement" msgid "Problem Statement"
msgstr "" msgstr "Opis problema"
#: frontend/src/pages/Billing.vue:129 #: frontend/src/pages/Billing.vue:129
msgid "Proceed to Payment" msgid "Proceed to Payment"
@@ -4695,34 +4695,34 @@ msgstr "Članovi programa"
#: frontend/src/components/Assessments.vue:249 #: frontend/src/components/Assessments.vue:249
msgid "Programming Exercise" msgid "Programming Exercise"
msgstr "" msgstr "Vežba programiranja"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:415 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:415
msgid "Programming Exercise Submission" msgid "Programming Exercise Submission"
msgstr "" msgstr "Podnesak vežbe programiranja"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:406 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:406
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:292 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:292
msgid "Programming Exercise Submissions" msgid "Programming Exercise Submissions"
msgstr "" msgstr "Podnesci vežbe programiranja"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:211 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:211
msgid "Programming Exercise created successfully" msgid "Programming Exercise created successfully"
msgstr "" msgstr "Vežba programiranja je uspešno kreirana"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:247 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:247
msgid "Programming Exercise deleted successfully" msgid "Programming Exercise deleted successfully"
msgstr "" msgstr "Vežba programiranja je uspešno obrisana"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:230 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:230
msgid "Programming Exercise updated successfully" msgid "Programming Exercise updated successfully"
msgstr "" msgstr "Vežba programiranja je uspešno ažurirana"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:302 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:302
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:157 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:157
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:165 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:165
msgid "Programming Exercises" msgid "Programming Exercises"
msgstr "" msgstr "Vežbe programiranja"
#: frontend/src/pages/Programs.vue:206 frontend/src/pages/Programs.vue:212 #: frontend/src/pages/Programs.vue:206 frontend/src/pages/Programs.vue:212
#: lms/www/lms.py:295 #: lms/www/lms.py:295
@@ -5224,7 +5224,7 @@ msgstr "Preostala mesta"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:23 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue:23
msgid "Select a Programming Exercise" msgid "Select a Programming Exercise"
msgstr "" msgstr "Izaberite vežbu programiranja"
#: frontend/src/components/Modals/Question.vue:98 #: frontend/src/components/Modals/Question.vue:98
msgid "Select a question" msgid "Select a question"
@@ -5637,11 +5637,11 @@ msgstr "Podneto od strane"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:348 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:348
msgid "Submission saved!" msgid "Submission saved!"
msgstr "" msgstr "Podnesak je sačuvan!"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:248 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:248
msgid "Submissions deleted successfully" msgid "Submissions deleted successfully"
msgstr "" msgstr "Podnesci su uspešno obrisani"
#: frontend/src/components/Modals/AssessmentModal.vue:9 #: frontend/src/components/Modals/AssessmentModal.vue:9
#: frontend/src/components/Modals/BatchCourseModal.vue:9 #: frontend/src/components/Modals/BatchCourseModal.vue:9
@@ -5786,7 +5786,7 @@ msgstr "Uslovi korišćenja"
#: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json #: lms/lms/doctype/lms_programming_exercise/lms_programming_exercise.json
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json #: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
msgid "Test Cases" msgid "Test Cases"
msgstr "" msgstr "Test primeri"
#. Label of the test_results (Small Text) field in DocType 'Exercise Latest #. Label of the test_results (Small Text) field in DocType 'Exercise Latest
#. Submission' #. Submission'
@@ -5799,11 +5799,11 @@ msgstr "Rezultati testa"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:82 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:82
msgid "Test this Exercise" msgid "Test this Exercise"
msgstr "" msgstr "Testiraj ovu vežbu"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:90 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:90
msgid "Test {0}" msgid "Test {0}"
msgstr "" msgstr "Test {0}"
#. Label of the tests (Code) field in DocType 'LMS Exercise' #. Label of the tests (Code) field in DocType 'LMS Exercise'
#: lms/lms/doctype/lms_exercise/lms_exercise.json #: lms/lms/doctype/lms_exercise/lms_exercise.json
@@ -5974,7 +5974,7 @@ msgstr "Vremenska preferencija"
#: frontend/src/components/VideoBlock.vue:140 #: frontend/src/components/VideoBlock.vue:140
msgid "Time for a Quiz" msgid "Time for a Quiz"
msgstr "" msgstr "Vreme za kviz"
#: frontend/src/components/Modals/QuizInVideo.vue:13 #: frontend/src/components/Modals/QuizInVideo.vue:13
msgid "Time in Video" msgid "Time in Video"
@@ -6642,7 +6642,7 @@ msgstr "Vaš nalog je uspešno kreiran!"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:117 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:117
msgid "Your Output" msgid "Your Output"
msgstr "" msgstr "Tvoj izlaz"
#: lms/lms/doctype/lms_batch/lms_batch.py:362 #: lms/lms/doctype/lms_batch/lms_batch.py:362
msgid "Your batch {0} is starting tomorrow" msgid "Your batch {0} is starting tomorrow"
@@ -6824,7 +6824,7 @@ msgstr "{0} zadataka"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:39 #: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:39
msgid "{0} Exercises" msgid "{0} Exercises"
msgstr "" msgstr "{0} vežbi"
#: frontend/src/pages/Jobs.vue:32 #: frontend/src/pages/Jobs.vue:32
msgid "{0} Open Jobs" msgid "{0} Open Jobs"
@@ -6840,7 +6840,7 @@ msgstr "{0} podešavanja nisu pronađena"
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:12 #: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmissions.vue:12
msgid "{0} Submissions" msgid "{0} Submissions"
msgstr "" msgstr "{0} podnesaka"
#: lms/templates/emails/job_application.html:2 #: lms/templates/emails/job_application.html:2
msgid "{0} has applied for the job position {1}" msgid "{0} has applied for the job position {1}"