chore: resolved conflicts
This commit is contained in:
@@ -144,20 +144,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="batch.data.evaluation_end_date && isStudent"
|
||||
class="text-sm leading-5 bg-surface-amber-1 text-ink-amber-3 p-2 rounded-md mb-10"
|
||||
>
|
||||
{{ __('The last day to schedule your evaluations is ') }}
|
||||
<span class="font-medium">
|
||||
{{
|
||||
dayjs(batch.data.evaluation_end_date).format('DD MMMM YYYY')
|
||||
}} </span
|
||||
>.
|
||||
{{
|
||||
__('Please make sure to schedule your evaluation before this date.')
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div v-if="dayjs().isSameOrAfter(dayjs(batch.data.start_date))">
|
||||
<div class="text-ink-gray-7 font-semibold mb-2">
|
||||
{{ __('Feedback') }}
|
||||
|
||||
@@ -281,21 +281,13 @@ import {
|
||||
import {
|
||||
Breadcrumbs,
|
||||
FormControl,
|
||||
FileUploader,
|
||||
Button,
|
||||
TextEditor,
|
||||
createResource,
|
||||
usePageMeta,
|
||||
toast,
|
||||
call,
|
||||
Toast,
|
||||
} from 'frappe-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Image, Trash2 } from 'lucide-vue-next'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import MultiSelect from '@/components/Controls/MultiSelect.vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import {
|
||||
escapeHTML,
|
||||
getMetaInfo,
|
||||
@@ -303,7 +295,13 @@ import {
|
||||
sanitizeHTML,
|
||||
updateMetaInfo,
|
||||
} from '@/utils'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Trash2 } from 'lucide-vue-next'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import Uploader from '@/components/Controls/Uploader.vue'
|
||||
import MultiSelect from '@/components/Controls/MultiSelect.vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const user = inject('$user')
|
||||
@@ -466,6 +464,7 @@ const validateFields = () => {
|
||||
!['description', 'batch_details'].includes(key) &&
|
||||
typeof batch[key] === 'string'
|
||||
) {
|
||||
console.log(key)
|
||||
batch[key] = escapeHTML(batch[key])
|
||||
}
|
||||
})
|
||||
|
||||
@@ -75,58 +75,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
<div class="mb-4">
|
||||
<div class="text-xs text-ink-gray-5 mb-2">
|
||||
{{ __('Course Image') }}
|
||||
</div>
|
||||
<FileUploader
|
||||
v-if="!course.course_image"
|
||||
:fileTypes="['image/*']"
|
||||
:validateFile="validateFile"
|
||||
@success="(file) => saveImage(file)"
|
||||
>
|
||||
<template
|
||||
v-slot="{ file, progress, uploading, openFileSelector }"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="border rounded-md w-fit py-5 px-20 cursor-pointer"
|
||||
@click="openFileSelector"
|
||||
>
|
||||
<Image class="size-5 stroke-1 text-ink-gray-7" />
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<Button @click="openFileSelector">
|
||||
{{ __('Upload') }}
|
||||
</Button>
|
||||
<div class="mt-1 text-ink-gray-5 text-sm leading-5">
|
||||
{{
|
||||
__('Appears on the course card in the course list')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
<div v-else class="mb-4">
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
:src="course.course_image.file_url"
|
||||
class="border rounded-md w-40"
|
||||
/>
|
||||
<div class="ml-4">
|
||||
<Button @click="removeImage()">
|
||||
{{ __('Remove') }}
|
||||
</Button>
|
||||
<div class="mt-2 text-ink-gray-5 text-sm">
|
||||
{{
|
||||
__('Appears on the course card in the course list')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Uploader
|
||||
v-model="course.image"
|
||||
:label="__('Course Image')"
|
||||
:required="false"
|
||||
/>
|
||||
|
||||
<ColorSwatches
|
||||
v-model="course.card_gradient"
|
||||
@@ -333,7 +286,6 @@ import {
|
||||
Button,
|
||||
createResource,
|
||||
FormControl,
|
||||
FileUploader,
|
||||
usePageMeta,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
@@ -347,22 +299,22 @@ import {
|
||||
watch,
|
||||
getCurrentInstance,
|
||||
} from 'vue'
|
||||
import { Image, Trash2, X } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import {
|
||||
escapeHTML,
|
||||
getMetaInfo,
|
||||
openSettings,
|
||||
sanitizeHTML,
|
||||
updateMetaInfo,
|
||||
validateFile,
|
||||
} from '@/utils'
|
||||
import { Trash2, X } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import CourseOutline from '@/components/CourseOutline.vue'
|
||||
import MultiSelect from '@/components/Controls/MultiSelect.vue'
|
||||
import ColorSwatches from '@/components/Controls/ColorSwatches.vue'
|
||||
import Uploader from '@/components/Controls/Uploader.vue'
|
||||
|
||||
const user = inject('$user')
|
||||
const newTag = ref('')
|
||||
@@ -386,7 +338,7 @@ const course = reactive({
|
||||
short_introduction: '',
|
||||
description: '',
|
||||
video_link: '',
|
||||
course_image: null,
|
||||
image: null,
|
||||
card_gradient: '',
|
||||
tags: '',
|
||||
category: '',
|
||||
@@ -448,7 +400,7 @@ const courseCreationResource = createResource({
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'LMS Course',
|
||||
image: course.course_image?.file_url || '',
|
||||
image: course.image,
|
||||
instructors: instructors.value.map((instructor) => ({
|
||||
instructor: instructor,
|
||||
})),
|
||||
@@ -469,7 +421,7 @@ const courseEditResource = createResource({
|
||||
doctype: 'LMS Course',
|
||||
name: values.course,
|
||||
fieldname: {
|
||||
image: course.course_image?.file_url || '',
|
||||
image: course.image,
|
||||
instructors: instructors.value.map((instructor) => ({
|
||||
instructor: instructor,
|
||||
})),
|
||||
@@ -519,24 +471,10 @@ const courseResource = createResource({
|
||||
course[key] = course[key] ? true : false
|
||||
}
|
||||
|
||||
if (data.image) imageResource.reload({ image: data.image })
|
||||
check_permission()
|
||||
},
|
||||
})
|
||||
|
||||
const imageResource = createResource({
|
||||
url: 'lms.lms.api.get_file_info',
|
||||
makeParams(values) {
|
||||
return {
|
||||
file_url: values.image,
|
||||
}
|
||||
},
|
||||
auto: false,
|
||||
onSuccess(data) {
|
||||
course.course_image = data
|
||||
},
|
||||
})
|
||||
|
||||
const validateFields = () => {
|
||||
course.description = sanitizeHTML(course.description)
|
||||
|
||||
@@ -580,16 +518,12 @@ const createCourse = () => {
|
||||
}
|
||||
|
||||
const editCourse = () => {
|
||||
let was_published = courseResource.data.published
|
||||
courseEditResource.submit(
|
||||
{
|
||||
course: courseResource.data.name,
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
if (!was_published && course.published) {
|
||||
capture('publish_course')
|
||||
}
|
||||
updateMetaInfo('courses', props.courseName, meta)
|
||||
toast.success(__('Course updated successfully'))
|
||||
},
|
||||
@@ -657,14 +591,6 @@ const removeTag = (tag) => {
|
||||
newTag.value = ''
|
||||
}
|
||||
|
||||
const saveImage = (file) => {
|
||||
course.course_image = file
|
||||
}
|
||||
|
||||
const removeImage = () => {
|
||||
course.course_image = null
|
||||
}
|
||||
|
||||
const check_permission = () => {
|
||||
let user_is_instructor = false
|
||||
if (user.data?.is_moderator) return
|
||||
|
||||
@@ -83,47 +83,11 @@
|
||||
class="mb-4"
|
||||
:required="true"
|
||||
/>
|
||||
<label class="block text-ink-gray-5 text-xs mb-1 mt-4">
|
||||
{{ __('Company Logo') }}
|
||||
<span class="text-ink-red-3">*</span>
|
||||
</label>
|
||||
<FileUploader
|
||||
v-if="!job.image"
|
||||
:fileTypes="['image/*']"
|
||||
:validateFile="validateFile"
|
||||
@success="(file) => saveImage(file)"
|
||||
>
|
||||
<template
|
||||
v-slot="{ file, progress, uploading, openFileSelector }"
|
||||
>
|
||||
<div class="mb-4">
|
||||
<Button @click="openFileSelector" :loading="uploading">
|
||||
{{
|
||||
uploading ? `Uploading ${progress}%` : 'Upload an image'
|
||||
}}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
<div v-else class="">
|
||||
<div class="flex items-center">
|
||||
<div class="border rounded-md p-2 mr-2">
|
||||
<FileText class="h-5 w-5 stroke-1.5 text-ink-gray-7" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span>
|
||||
{{ job.image.file_name }}
|
||||
</span>
|
||||
<span class="text-sm text-ink-gray-4 mt-1">
|
||||
{{ getFileSize(job.image.file_size) }}
|
||||
</span>
|
||||
</div>
|
||||
<X
|
||||
@click="removeImage()"
|
||||
class="bg-surface-gray-3 rounded-md cursor-pointer stroke-1.5 w-5 h-5 p-1 ml-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Uploader
|
||||
v-model="job.company_logo"
|
||||
:label="__('Company Logo')"
|
||||
:required="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -150,15 +114,14 @@ import {
|
||||
createResource,
|
||||
Button,
|
||||
TextEditor,
|
||||
FileUploader,
|
||||
usePageMeta,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { computed, onMounted, reactive, inject } from 'vue'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { escapeHTML, getFileSize, sanitizeHTML, validateFile } from '@/utils'
|
||||
import { escapeHTML, sanitizeHTML } from '@/utils'
|
||||
import Uploader from '@/components/Controls/Uploader.vue'
|
||||
|
||||
const user = inject('$user')
|
||||
const router = useRouter()
|
||||
@@ -177,7 +140,7 @@ const newJob = createResource({
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'Job Opportunity',
|
||||
company_logo: job.image?.file_url,
|
||||
company_logo: job.company_logo,
|
||||
...job,
|
||||
},
|
||||
}
|
||||
@@ -191,7 +154,7 @@ const updateJob = createResource({
|
||||
doctype: 'Job Opportunity',
|
||||
name: props.jobName,
|
||||
fieldname: {
|
||||
company_logo: job.image.file_url,
|
||||
company_logo: job.company_logo,
|
||||
...job,
|
||||
},
|
||||
}
|
||||
@@ -215,20 +178,6 @@ const jobDetail = createResource({
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (Object.hasOwn(job, key)) job[key] = data[key]
|
||||
})
|
||||
if (data.company_logo) imageResource.reload({ image: data.company_logo })
|
||||
},
|
||||
})
|
||||
|
||||
const imageResource = createResource({
|
||||
url: 'lms.lms.api.get_file_info',
|
||||
makeParams(values) {
|
||||
return {
|
||||
file_url: values.image,
|
||||
}
|
||||
},
|
||||
auto: false,
|
||||
onSuccess(data) {
|
||||
job.image = data
|
||||
},
|
||||
})
|
||||
|
||||
@@ -241,7 +190,7 @@ const job = reactive({
|
||||
status: 'Open',
|
||||
company_name: '',
|
||||
company_website: '',
|
||||
image: null,
|
||||
company_logo: null,
|
||||
description: '',
|
||||
company_email_address: '',
|
||||
})
|
||||
@@ -322,14 +271,6 @@ const validateJobFields = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const saveImage = (file) => {
|
||||
job.image = file
|
||||
}
|
||||
|
||||
const removeImage = () => {
|
||||
job.image = null
|
||||
}
|
||||
|
||||
const jobTypes = computed(() => {
|
||||
return [
|
||||
{ label: 'Full Time', value: 'Full Time' },
|
||||
|
||||
@@ -665,6 +665,15 @@ iframe {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.codex-editor--narrow .ce-toolbox .ce-popover {
|
||||
right: unset;
|
||||
left: initial;
|
||||
}
|
||||
|
||||
.ce-popover {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.cdx-search-field {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,6 @@ import { ClipboardList, ListChecks, Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { escapeHTML } from '@/utils'
|
||||
import Question from '@/components/Modals/Question.vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const { brand } = sessionStore()
|
||||
const showQuestionModal = ref(false)
|
||||
@@ -242,7 +241,6 @@ const currentQuestion = reactive({
|
||||
marks: 0,
|
||||
name: '',
|
||||
})
|
||||
const { capture } = useTelemetry()
|
||||
const user = inject('$user')
|
||||
const router = useRouter()
|
||||
const readOnlyMode = window.read_only_mode
|
||||
@@ -260,9 +258,7 @@ onMounted(() => {
|
||||
if (!user.data?.is_moderator && !user.data?.is_instructor) {
|
||||
router.push({ name: 'Courses' })
|
||||
}
|
||||
if (props.quizID !== 'new') {
|
||||
quizDetails.reload()
|
||||
}
|
||||
quizDetails.reload()
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
|
||||
@@ -310,9 +306,6 @@ const submitQuiz = () => {
|
||||
},
|
||||
{
|
||||
onSuccess(data) {
|
||||
if (props.quizID === 'new') {
|
||||
capture('quiz_created')
|
||||
}
|
||||
quizDetails.doc.total_marks = data.total_marks
|
||||
toast.success(__('Quiz updated successfully'))
|
||||
},
|
||||
@@ -408,7 +401,7 @@ const breadcrumbs = computed(() => {
|
||||
]
|
||||
|
||||
crumbs.push({
|
||||
label: props.quizID == 'new' ? __('New Quiz') : quizDetails.doc?.title,
|
||||
label: quizDetails.doc?.title,
|
||||
route: { name: 'QuizForm', params: { quizID: props.quizID } },
|
||||
})
|
||||
return crumbs
|
||||
@@ -416,7 +409,7 @@ const breadcrumbs = computed(() => {
|
||||
|
||||
usePageMeta(() => {
|
||||
return {
|
||||
title: props.quizID == 'new' ? __('New Quiz') : quizDetails.doc?.title,
|
||||
title: quizDetails.doc?.title,
|
||||
icon: brand.favicon,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user