@@ -107,7 +107,7 @@ async function setLanguageExtension() {
|
||||
if (!languageImport) return
|
||||
|
||||
const module = await languageImport()
|
||||
languageExtension.value = (module as any)[props.language]()
|
||||
languageExtension.value = (module as any)[props.language]?.()
|
||||
|
||||
if (props.completions) {
|
||||
const languageData = (module as any)[`${props.language}Language`]
|
||||
|
||||
@@ -76,7 +76,14 @@ const isIos = () => {
|
||||
const isInStandaloneMode = () =>
|
||||
'standalone' in window.navigator && window.navigator.standalone
|
||||
|
||||
if (isIos() && !isInStandaloneMode()) iosInstallMessage.value = true
|
||||
if (
|
||||
isIos() &&
|
||||
!isInStandaloneMode() &&
|
||||
localStorage.getItem('learningIosInstallPromptShown') !== 'true'
|
||||
) {
|
||||
iosInstallMessage.value = true
|
||||
localStorage.setItem('learningIosInstallPromptShown', 'true')
|
||||
}
|
||||
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
</Button>
|
||||
</div>
|
||||
<div v-if="upcoming_evals.data?.length">
|
||||
<div class="grid gap-4" :class="forHome ? 'grid-cols-2' : 'grid-cols-3'">
|
||||
<div
|
||||
class="grid gap-4"
|
||||
:class="forHome ? 'grid-cols-1 md:grid-cols-2' : 'grid-cols-3'"
|
||||
>
|
||||
<div v-for="evl in upcoming_evals.data">
|
||||
<div class="border text-ink-gray-7 rounded-md p-3">
|
||||
<div class="flex justify-between mb-3">
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-5 mt-10">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-5 mt-10">
|
||||
<UpcomingEvaluations :forHome="true" />
|
||||
<div v-if="myLiveClasses.data?.length">
|
||||
<div class="font-semibold text-lg mb-3 text-ink-gray-9">
|
||||
|
||||
@@ -66,38 +66,38 @@
|
||||
v-if="column.key === 'full_name'"
|
||||
class="flex items-center space-x-3"
|
||||
>
|
||||
<img
|
||||
v-if="row.user_image"
|
||||
:src="row.user_image"
|
||||
:alt="row.full_name"
|
||||
class="w-8 h-8 rounded-full object-cover"
|
||||
<Avatar
|
||||
size="sm"
|
||||
:image="row['user_image']"
|
||||
:label="row['full_name']"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="w-8 h-8 rounded-full bg-surface-gray-3 flex items-center justify-center"
|
||||
>
|
||||
<FeatherIcon name="user" class="w-4 h-4 text-ink-gray-6" />
|
||||
</div>
|
||||
<span class="text-sm font-medium">{{ item }}</span>
|
||||
|
||||
<span>{{ item }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="column.key === 'actions'"
|
||||
class="flex justify-center"
|
||||
>
|
||||
<Dropdown :options="getActionOptions(row)">
|
||||
<Button variant="ghost" size="sm">
|
||||
<Button variant="ghost">
|
||||
<FeatherIcon name="more-horizontal" class="w-4 h-4" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div v-else class="text-sm">
|
||||
<div
|
||||
v-else-if="column.key === 'applied_on'"
|
||||
class="text-sm text-ink-gray-6"
|
||||
>
|
||||
{{ item }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ item }}
|
||||
</div>
|
||||
</ListRowItem>
|
||||
</ListRow>
|
||||
</ListRows>
|
||||
</ListView>
|
||||
<EmptyState v-else type="Applications" />
|
||||
<EmptyState v-else-if="!applications.loading" type="Job Applications" />
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
@@ -147,6 +147,7 @@
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Breadcrumbs,
|
||||
Dialog,
|
||||
@@ -252,6 +253,7 @@ const sendEmail = (close) => {
|
||||
}
|
||||
|
||||
const downloadResume = (resumeUrl) => {
|
||||
console.log(resumeUrl)
|
||||
window.open(resumeUrl, '_blank')
|
||||
}
|
||||
|
||||
@@ -288,7 +290,7 @@ const applicationColumns = computed(() => {
|
||||
},
|
||||
{
|
||||
label: __('Applied On'),
|
||||
key: 'applied_date',
|
||||
key: 'applied_on',
|
||||
width: 1,
|
||||
icon: 'calendar',
|
||||
},
|
||||
@@ -305,7 +307,7 @@ const applicantRows = computed(() => {
|
||||
return applications.data.map((application) => ({
|
||||
...application,
|
||||
full_name: application.full_name,
|
||||
applied_date: dayjs(application.creation).format('MMM DD, YYYY'),
|
||||
applied_on: dayjs(application.creation).fromNow(),
|
||||
}))
|
||||
})
|
||||
|
||||
|
||||
@@ -190,15 +190,22 @@ const isSessionUser = () => {
|
||||
return $user.data?.email === profile.data?.email
|
||||
}
|
||||
|
||||
const hasHigherAccess = () => {
|
||||
const currentUserHasHigherAccess = () => {
|
||||
return $user.data?.is_evaluator || $user.data?.is_moderator
|
||||
}
|
||||
|
||||
const isEvaluatorOrModerator = () => {
|
||||
return (
|
||||
profile.data?.roles?.includes('Batch Evaluator') ||
|
||||
profile.data?.roles?.includes('Moderator')
|
||||
)
|
||||
}
|
||||
|
||||
const getTabButtons = () => {
|
||||
let buttons = [{ label: 'About' }, { label: 'Certificates' }]
|
||||
if ($user.data?.is_moderator) buttons.push({ label: 'Roles' })
|
||||
|
||||
if (hasHigherAccess()) {
|
||||
if (currentUserHasHigherAccess() && isEvaluatorOrModerator()) {
|
||||
buttons.push({ label: 'Slots' })
|
||||
buttons.push({ label: 'Schedule' })
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ const hasHigherAccess = () => {
|
||||
}
|
||||
|
||||
const isSessionUser = () => {
|
||||
return user.data?.email === props.profile.data?.email
|
||||
return user.data?.email === props.profile.data?.name
|
||||
}
|
||||
|
||||
const showSlotsTemplate = ref(0)
|
||||
|
||||
@@ -266,8 +266,7 @@ const checkIfUserIsPermitted = (doc: any = null) => {
|
||||
!user.data.is_evaluator
|
||||
) {
|
||||
router.push({
|
||||
name: 'ProgrammingExerciseSubmission',
|
||||
params: { exerciseID: props.exerciseID, submissionID: 'new' },
|
||||
name: 'Courses',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1674,9 +1674,12 @@ def get_pwa_manifest():
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_profile_details(username):
|
||||
return frappe.db.get_value(
|
||||
details = frappe.db.get_value(
|
||||
"User",
|
||||
{"username": username},
|
||||
["full_name", "name", "username", "user_image", "bio", "headline", "cover_image"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
details.roles = frappe.get_roles(details.name)
|
||||
return details
|
||||
|
||||
@@ -83,8 +83,8 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-04 12:04:11.007945",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-11-10 11:41:51.802016",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "Course Evaluator",
|
||||
"naming_rule": "By fieldname",
|
||||
@@ -131,5 +131,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "full_name"
|
||||
"title_field": "full_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -70,10 +70,11 @@
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-12-24 09:36:31.464508",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-11-10 11:40:38.157448",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Assignment",
|
||||
"naming_rule": "Expression (old style)",
|
||||
@@ -113,9 +114,11 @@
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"show_title_field_in_link": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "title"
|
||||
}
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-11-06 11:38:35.903520",
|
||||
"modified": "2025-11-10 11:39:42.233779",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Badge Assignment",
|
||||
@@ -166,5 +166,6 @@
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "member"
|
||||
"title_field": "member",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -131,10 +131,11 @@
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-09-11 11:20:06.233491",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-11-10 11:41:38.999620",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Certificate Evaluation",
|
||||
"owner": "Administrator",
|
||||
@@ -164,6 +165,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [
|
||||
@@ -184,5 +186,6 @@
|
||||
"title": "In Progress"
|
||||
}
|
||||
],
|
||||
"title_field": "member_name"
|
||||
}
|
||||
"title_field": "member_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-10-13 14:30:57.897102",
|
||||
"modified": "2025-11-10 11:40:50.679211",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Certificate Request",
|
||||
@@ -228,5 +228,6 @@
|
||||
"title": "Cancelled"
|
||||
}
|
||||
],
|
||||
"title_field": "member_name"
|
||||
"title_field": "member_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -193,11 +193,12 @@
|
||||
"label": "Possible Answer 4"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"make_attachments_public": 1,
|
||||
"modified": "2024-10-07 09:41:17.862774",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-11-10 11:40:18.568547",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Question",
|
||||
"naming_rule": "Expression",
|
||||
@@ -240,8 +241,10 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "question"
|
||||
}
|
||||
"title_field": "question",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
"unique": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2023-10-26 17:25:09.144367",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-11-10 11:39:57.251861",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Source",
|
||||
"naming_rule": "By fieldname",
|
||||
@@ -62,8 +63,10 @@
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "source"
|
||||
}
|
||||
"title_field": "source",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-08 12:20:48.314056",
|
||||
"modified": "2025-11-10 11:39:13.146961",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Zoom Settings",
|
||||
@@ -131,5 +131,6 @@
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user