Skip to content

Commit 844e09f

Browse files
authored
Merge pull request #2313 from frappe/main-hotfix
chore: merge 'main-hotfix' into 'main'
2 parents cb9b54a + 4f96e2d commit 844e09f

28 files changed

Lines changed: 713 additions & 368 deletions

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ jobs:
3838

3939
- name: Set Branch
4040
run: |
41-
export APPS_JSON='[{"url": "https://github.com/frappe/lms","branch": "main"}]'
41+
export APPS_JSON='[{"url": "https://github.com/frappe/payments","branch": "version-15"},{"url": "https://github.com/frappe/lms","branch": "main"}]'
4242
echo "APPS_JSON_BASE64=$(echo $APPS_JSON | base64 -w 0)" >> $GITHUB_ENV
43-
echo "FRAPPE_BRANCH=version-15" >> $GITHUB_ENV
43+
echo "FRAPPE_BRANCH=version-16" >> $GITHUB_ENV
4444
4545
- name: Set Image Tag
4646
run: |
@@ -61,4 +61,4 @@ jobs:
6161
ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
6262
build-args: |
6363
"FRAPPE_BRANCH=${{ env.FRAPPE_BRANCH }}"
64-
"APPS_JSON_BASE64=${{ env.APPS_JSON_BASE64 }}"
64+
"APPS_JSON_BASE64=${{ env.APPS_JSON_BASE64 }}"

docker/init.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ bench set-redis-socketio-host redis://redis:6379
2424
sed -i '/redis/d' ./Procfile
2525
sed -i '/watch/d' ./Procfile
2626

27+
bench get-app payments
2728
bench get-app lms
2829

2930
bench new-site lms.localhost \
@@ -32,6 +33,7 @@ bench new-site lms.localhost \
3233
--admin-password admin \
3334
--no-mariadb-socket
3435

36+
bench --site lms.localhost install-app payments
3537
bench --site lms.localhost install-app lms
3638
bench --site lms.localhost set-config developer_mode 1
3739
bench --site lms.localhost clear-cache

frontend/src/components/Assignment.vue

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</div>
1818
</div>
1919
<div class="text-ink-gray-9 font-semibold mb-5">
20-
{{ __('Assignment Question') }}
20+
{{ __('Assignment') }}: {{ assignment.data.title }}
2121
</div>
2222
<div
2323
v-html="assignment.data.question"
@@ -300,7 +300,7 @@ const submitAssignment = () => {
300300
}
301301
}
302302
303-
const addNewSubmission = () => {
303+
const prepareSubmissionDoc = () => {
304304
let doc = {
305305
doctype: 'LMS Assignment Submission',
306306
assignment: props.assignmentID,
@@ -311,24 +311,31 @@ const addNewSubmission = () => {
311311
} else {
312312
doc.assignment_attachment = attachment.value
313313
}
314+
return doc
315+
}
316+
317+
const addNewSubmission = () => {
318+
let doc = prepareSubmissionDoc()
319+
if (!doc.assignment_attachment && !doc.answer) {
320+
toast.error(
321+
__('Please provide an answer or upload a file before submitting.')
322+
)
323+
return
324+
}
314325
call('frappe.client.insert', {
315326
doc: doc,
316327
})
317328
.then((data) => {
318329
toast.success(__('Assignment submitted successfully'))
319-
if (router.currentRoute.value.name == 'AssignmentSubmission') {
320-
router.push({
321-
name: 'AssignmentSubmission',
322-
params: {
323-
assignmentID: props.assignmentID,
324-
submissionName: data.name,
325-
},
326-
query: { fromLesson: router.currentRoute.value.query.fromLesson },
327-
})
328-
} else {
329-
markLessonProgress()
330-
router.go()
331-
}
330+
router.push({
331+
name: 'AssignmentSubmission',
332+
params: {
333+
assignmentID: props.assignmentID,
334+
submissionName: data.name,
335+
},
336+
query: { fromLesson: router.currentRoute.value.query.fromLesson },
337+
})
338+
markLessonProgress()
332339
isDirty.value = false
333340
submissionResource.name = data.name
334341
submissionResource.reload()
@@ -372,15 +379,17 @@ const saveSubmission = (file) => {
372379
}
373380
374381
const markLessonProgress = () => {
375-
if (router.currentRoute.value.name == 'Lesson') {
376-
let courseName = router.currentRoute.value.params.courseName
377-
let chapterNumber = router.currentRoute.value.params.chapterNumber
378-
let lessonNumber = router.currentRoute.value.params.lessonNumber
382+
let pathname = window.location.pathname.split('/')
383+
if (!pathname.includes('courses'))
384+
pathname = window.parent.location.pathname.split('/')
385+
if (pathname[2] != 'courses') return
386+
let lessonIndex = pathname.pop().split('-')
379387
388+
if (lessonIndex.length == 2) {
380389
call('lms.lms.api.mark_lesson_progress', {
381-
course: courseName,
382-
chapter_number: chapterNumber,
383-
lesson_number: lessonNumber,
390+
course: pathname[3],
391+
chapter_number: lessonIndex[0],
392+
lesson_number: lessonIndex[1],
384393
})
385394
}
386395
}

frontend/src/components/CourseCard.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div
33
v-if="course.title"
4-
class="flex flex-col h-full rounded-md overflow-auto text-ink-gray-9"
4+
class="flex flex-col h-full rounded-md overflow-auto text-ink-gray-9 bg-surface-cards"
55
style="min-height: 350px"
66
>
77
<div
@@ -10,7 +10,7 @@
1010
course.image
1111
? { backgroundImage: `url('${encodeURI(course.image)}')` }
1212
: {
13-
backgroundImage: getGradientColor(),
13+
backgroundImage: gradientColor,
1414
backgroundBlendMode: 'screen',
1515
}
1616
"
@@ -137,6 +137,8 @@ import { Award, BookOpen, GraduationCap, Star, Users } from 'lucide-vue-next'
137137
import { sessionStore } from '@/stores/session'
138138
import { Tooltip } from 'frappe-ui'
139139
import { formatAmount } from '@/utils'
140+
import { theme } from '@/utils/theme'
141+
import { computed, watch } from 'vue'
140142
import CourseInstructors from '@/components/CourseInstructors.vue'
141143
import UserAvatar from '@/components/UserAvatar.vue'
142144
import ProgressBar from '@/components/ProgressBar.vue'
@@ -151,12 +153,12 @@ const props = defineProps({
151153
},
152154
})
153155
154-
const getGradientColor = () => {
155-
let theme = localStorage.getItem('theme') == 'dark' ? 'darkMode' : 'lightMode'
156+
const gradientColor = computed(() => {
157+
let themeMode = theme.value === 'dark' ? 'darkMode' : 'lightMode'
156158
let color = props.course.card_gradient?.toLowerCase() || 'blue'
157-
let colorMap = colors[theme][color]
159+
let colorMap = colors[themeMode][color]
158160
return `linear-gradient(to top right, black, ${colorMap[400]})`
159-
}
161+
})
160162
</script>
161163
<style>
162164
.course-card-pills {

frontend/src/components/MobileLayout.vue

Lines changed: 51 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
import { getSidebarLinks } from '@/utils'
5858
import { useRouter } from 'vue-router'
5959
import { call } from 'frappe-ui'
60-
import { watch, ref, onMounted } from 'vue'
60+
import { ref, watch } from 'vue'
6161
import { sessionStore } from '@/stores/session'
6262
import { useSettings } from '@/stores/settings'
6363
import { usersStore } from '@/stores/user'
@@ -68,26 +68,13 @@ let { isLoggedIn } = sessionStore()
6868
const { sidebarSettings } = useSettings()
6969
const router = useRouter()
7070
let { userResource } = usersStore()
71-
const sidebarLinks = ref(getSidebarLinks())
71+
const sidebarLinks = ref([])
7272
const otherLinks = ref([])
7373
const showMenu = ref(false)
7474
const menu = ref(null)
7575
const isModerator = ref(false)
7676
const isInstructor = ref(false)
7777
78-
onMounted(() => {
79-
sidebarSettings.reload(
80-
{},
81-
{
82-
onSuccess(data) {
83-
destructureSidebarLinks()
84-
filterLinksToShow(data)
85-
addOtherLinks()
86-
},
87-
}
88-
)
89-
})
90-
9178
const handleOutsideClick = (e) => {
9279
if (menu.value && !menu.value.contains(e.target)) {
9380
showMenu.value = false
@@ -126,65 +113,57 @@ const filterLinksToShow = (data) => {
126113
127114
const addOtherLinks = () => {
128115
if (user) {
129-
otherLinks.value.push({
130-
label: 'Notifications',
131-
icon: 'Bell',
132-
to: 'Notifications',
133-
})
134-
otherLinks.value.push({
135-
label: 'Profile',
136-
icon: 'UserRound',
137-
})
138-
otherLinks.value.push({
139-
label: 'Log out',
140-
icon: 'LogOut',
141-
})
116+
addLink('Notifications', 'Bell', 'Notifications')
117+
addLink('Profile', 'UserRound')
118+
addLink('Log out', 'LogOut')
142119
} else {
143-
otherLinks.value.push({
144-
label: 'Log in',
145-
icon: 'LogIn',
146-
})
120+
addLink('Log in', 'LogIn')
147121
}
148122
}
149123
150-
watch(userResource, () => {
151-
if (userResource.data) {
152-
isModerator.value = userResource.data.is_moderator
153-
isInstructor.value = userResource.data.is_instructor
154-
addPrograms()
155-
if (isModerator.value || isInstructor.value) {
156-
addProgrammingExercises()
157-
addQuizzes()
158-
addAssignments()
124+
const addLink = (label, icon, to = '') => {
125+
if (otherLinks.value.some((link) => link.label === label)) return
126+
otherLinks.value.push({
127+
label: label,
128+
icon: icon,
129+
to: to,
130+
})
131+
}
132+
133+
const updateSidebarLinks = () => {
134+
sidebarLinks.value = getSidebarLinks(true)
135+
destructureSidebarLinks()
136+
sidebarSettings.reload(
137+
{},
138+
{
139+
onSuccess: async (data) => {
140+
filterLinksToShow(data)
141+
await addPrograms()
142+
if (isModerator.value || isInstructor.value) {
143+
addQuizzes()
144+
addAssignments()
145+
addProgrammingExercises()
146+
}
147+
addOtherLinks()
148+
},
159149
}
160-
}
161-
})
150+
)
151+
}
162152
163153
const addQuizzes = () => {
164-
otherLinks.value.push({
165-
label: 'Quizzes',
166-
icon: 'CircleHelp',
167-
to: 'Quizzes',
168-
})
154+
addLink('Quizzes', 'CircleHelp', 'Quizzes')
169155
}
170156
171157
const addAssignments = () => {
172-
otherLinks.value.push({
173-
label: 'Assignments',
174-
icon: 'Pencil',
175-
to: 'Assignments',
176-
})
158+
addLink('Assignments', 'Pencil', 'Assignments')
177159
}
178160
179161
const addProgrammingExercises = () => {
180-
otherLinks.value.push({
181-
label: 'Programming Exercises',
182-
icon: 'Code',
183-
to: 'ProgrammingExercises',
184-
})
162+
addLink('Programming Exercises', 'Code', 'ProgrammingExercises')
185163
}
186164
187165
const addPrograms = async () => {
166+
if (sidebarLinks.value.some((link) => link.label === 'Programs')) return
188167
let canAddProgram = await checkIfCanAddProgram()
189168
if (!canAddProgram) return
190169
let activeFor = ['Programs', 'ProgramDetail']
@@ -198,7 +177,21 @@ const addPrograms = async () => {
198177
})
199178
}
200179
180+
watch(
181+
userResource,
182+
async () => {
183+
await userResource.promise
184+
if (userResource.data) {
185+
isModerator.value = userResource.data.is_moderator
186+
isInstructor.value = userResource.data.is_instructor
187+
}
188+
updateSidebarLinks()
189+
},
190+
{ immediate: true }
191+
)
192+
201193
const checkIfCanAddProgram = async () => {
194+
if (!userResource.data) return false
202195
if (isModerator.value || isInstructor.value) {
203196
return true
204197
}

frontend/src/components/Quiz.vue

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@
224224
</div>
225225
<div class="flex items-center justify-between mt-8">
226226
<Checkbox
227+
v-if="!quiz.data.show_answers"
227228
:label="__('Mark for review')"
228229
:model-value="reviewQuestions.includes(activeQuestion) ? 1 : 0"
229230
@change="markForReview($event, activeQuestion)"
@@ -278,6 +279,7 @@
278279
!showAnswers.length &&
279280
questionDetails.data.type != 'Open Ended'
280281
"
282+
class="ml-auto"
281283
@click="checkAnswer()"
282284
>
283285
<span>
@@ -289,12 +291,18 @@
289291
activeQuestion != questions.length && quiz.data.show_answers
290292
"
291293
@click="nextQuestion()"
294+
class="ml-auto"
292295
>
293296
<span>
294297
{{ __('Next') }}
295298
</span>
296299
</Button>
297-
<Button variant="solid" v-else @click="handleSubmitClick()">
300+
<Button
301+
variant="solid"
302+
v-else
303+
@click="handleSubmitClick()"
304+
class="ml-auto"
305+
>
298306
<span>
299307
{{ __('Submit') }}
300308
</span>
@@ -891,10 +899,14 @@ const markLessonProgress = () => {
891899
}
892900
893901
const handleSubmitClick = () => {
894-
if (attemptedQuestions.value.length) {
895-
switchQuestion(activeQuestion.value)
902+
if (!quiz.data.show_answers) {
903+
if (attemptedQuestions.value.length) {
904+
switchQuestion(activeQuestion.value)
905+
}
906+
showSubmissionConfirmation.value = true
907+
} else {
908+
submitQuiz()
896909
}
897-
showSubmissionConfirmation.value = true
898910
}
899911
900912
const paginationWindow = computed(() => {

0 commit comments

Comments
 (0)